Tag: ieee 754

为什么在这个C代码中使用的IEEE-754指数偏差是126.94269504而不是127?

以下C函数来自fastapprox项目。 static inline float fasterlog2 (float x) { union { float f; uint32_t i; } vx = { x }; float y = vx.i; y *= 1.1920928955078125e-7f; return y – 126.94269504f; } 有些专家可以解释一下为什么上面代码中使用的指数偏差是126.94269504而不是127? 是否更准确的偏差值?

最快的算法,用于识别制作双精度方程x + a == b true的最小和最大x

在静态分析的上下文中,我感兴趣的是在以下条件的then-branch中确定x的值: double x; x = …; if (x + a == b) { … a和b可以假设为双精度常量(推广到任意表达式是问题中最容易的部分),并且可以假设编译器严格遵循IEEE 754( FLT_EVAL_METHOD为0)。 运行时的舍入模式可以假设为最接近均匀。 如果用有理数计算是便宜的,那就很简单: x的值将是理性区间中包含的双精度数(b – a – 0.5 * ulp1(b)… b – a + 0.5 * ulp2(b) )。 如果b是偶数,则应该包括边界,如果b是奇数则排除,并且ulp1和ulp2是两个稍微不同的“ULP”定义,如果不介意在2的幂上失去一点精度,则可以采用相同的定义。 不幸的是,使用有理数的计算可能很昂贵。 考虑另一种可能性是通过二分法获得每个边界,在64个双精度加法中(每个操作决定结果的一位)。 获得下限和上限的128个浮点加法可能比基于数学的任何解更快。 我想知道是否有办法改进“128浮点添加”的想法。 实际上我有自己的解决方案,包括更改舍入模式和nextafter调用,但我不想吝啬任何人的风格,并使他们错过比我现有的更优雅的解决方案。 另外我不确定两次更改舍入模式实际上比64个浮点加法更便宜。

IEEE754浮点值的便携式序列化

我最近一直致力于一个需要存储和加载大量数据的系统,包括单精度浮点值。 我决定标准化整数的网络字节顺序,并决定以big-endian格式存储浮点值,即: |– Byte 0 –| |– Byte 1 -| Byte 2 Byte 3 # ####### # ####### ######## ######## Sign Exponent Mantissa 1b 8b, MSB first 23b, MSB first 理想情况下,我想提供像htonl()和ntohl()这样的函数,因为我已经使用它们来擦除整数,我也希望以尽可能多的平台独立性的方式实现它(同时假设float类型对应于IEEE754 32位浮点值)。 有没有办法,可能使用ieee754.h ,这样做? 我有一个似乎有效的答案,我将在下面发布,但它似乎非常缓慢和低效,我将不胜感激任何有关如何使其更快和/或更可靠的建议。

为什么pow(-infinity,正非整数)+无限?

C99附件F(IEEE浮点支持)说: 对于y> 0而言, pow(−∞, y)返回+∞而不是奇数。 但是,比方说,( – ∞) 0.5实际上有虚数值±∞i,而不是+∞。 C99自己的sqrt(−∞)返回NaN并按预期生成域错误。 那么为什么需要返回+∞? (大多数其他语言直接使用C库,或者像本例中的Python一样,通过标准复制它所需的行为,因此在实践中这不仅仅影响C99。)

如何将IEEE 754单精度二进制浮点数转换为十进制?

我正在研究一个需要将32位数转换为十进制数的程序。 我从输入中得到的数字是一个32位数字,表示为浮点数。 第一位是符号,接下来的8位是指数,其他23位是尾数。 我在C中使用该程序。在输入中,我将该数字作为char[]数组,然后我创建一个新的int[]数组,其中存储符号,指数和尾数。 但是,当我试图将它存储在某种数据类型中时,我对尾数有问题,因为我需要将尾数用作数字,而不是数组: formula=sign*(1+0.mantissa)*2^(exponent-127) 。 这是我用来存储尾数的代码,但程序仍然会得到错误的结果: double oMantissa=0; int counter=0; for(counter=0;counter<23;counter++) { if(mantissa[counter]==1) { oMantissa+=mantissa[counter]*pow(10,-counter); } } mantissa[]是一个int数组,我已经从char数组中转换了尾数。 当我从formula得到值时,它必须是二进制数,我必须将其转换为十进制,所以我将得到数字的值。 你可以帮我存储23位的尾数吗? 并且,我不能使用像strtoul这样的函数将32位数字直接转换为二进制数。 我必须使用formula 。

浮点运算的准确性

我无法理解这个程序的输出 int main() { double x = 1.8939201459282359e-308; double y = 4.9406564584124654e-324; printf(“%23.16e\n”, 1.6*y); printf(“%23.16e\n”, 1.7*y); printf(“%23.16e\n”, 1.8*y); printf(“%23.16e\n”, 1.9*y); printf(“%23.16e\n”, 2.0*y); printf(“%23.16e\n”, x + 1.6*y); printf(“%23.16e\n”, x + 1.7*y); printf(“%23.16e\n”, x + 1.8*y); printf(“%23.16e\n”, x + 1.9*y); printf(“%23.16e\n”, x + 2.0*y); } 输出是 9.8813129168249309e-324 9.8813129168249309e-324 9.8813129168249309e-324 9.8813129168249309e-324 9.8813129168249309e-324 1.8939201459282364e-308 1.8939201459282364e-308 1.8939201459282369e-308 1.8939201459282369e-308 1.8939201459282369e-308 我正在使用IEEE算法。 […]

如何检查float是否可以精确表示为整数

我正在寻找一种合理有效的方法来确定浮点值( double )是否可以由整数数据类型( long ,64位)精确表示。 我最初的想法是检查指数是否为0 (或更准确地说是127 )。 但这不起作用,因为2.0将是e = 1 m = 1 … 所以基本上,我被卡住了。 我有一种感觉,我可以使用位掩码做到这一点,但我现在还没有理解如何做到这一点。 那么我怎样才能检查一个double是否可以完全表示为long? 谢谢

使用c – printf将ieee 754 float转换为hex

理想情况下,以下代码将采用IEEE 754表示forms的浮点数并将其转换为hex void convert() //gets the float input from user and turns it into hexadecimal { float f; printf(“Enter float: “); scanf(“%f”, &f); printf(“hex is %x”, f); } 我不太确定会出现什么问题。 它将数字转换为hex数,但却是一个非常错误的数字。 123.1443 gives 40000000 43.3 gives 60000000 8 gives 0 所以它正在做某事,我只是不太确定是什么。 帮助将不胜感激

浮点运算中的flush-to-zero行为

虽然,据我所知,IEEE 754没有提及关于刷新到零模式来更快地处理非规范化数字 ,但是一些架构提供了这种模式(例如http://docs.sun.com/source/806-3568/ncg_lib .html )。 在本技术文档的特定情况下,非规范化数字的标准处理是默认值,并且必须明确激活flush-to-zero。 在默认模式下,非规范化数字也在软件中处理,这比较慢。 我在嵌入式C的静态分析器上工作,试图预测在运行时可能发生的值的正确(如果有时是不精确的)范围。 它的目的是正确的,因为它可用于排除在运行时出现错误的可能性(例如对于关键的嵌入式代码)。 这需要在分析期间捕获所有可能的行为,因此在浮点计算期间产生所有可能的值。 在这方面,我的问题是双重的: 在嵌入式架构中,是否存在仅提供从零到零的架构 ? 他们可能没有权利将自己宣传为“IEEE 754”,但可以提供足够接近IEEE 754风格的浮点运算。 对于在嵌入式环境中提供两者的体系结构, 可能不会被系统激活为零 ,以使反应时间更可预测(这些嵌入式系统的常见约束)? 在我用于浮点值的区间运算中处理flush-to-zero非常简单,如果我知道我必须这样做,我的问题是我是否必须这样做。

从双精度参数开始的80位扩展精度计算的属性

以下是插值函数的两种实现。 参数u1始终在0.和1.之间。 #include double interpol_64(double u1, double u2, double u3) { return u2 * (1.0 – u1) + u1 * u3; } double interpol_80(double u1, double u2, double u3) { return u2 * (1.0 – (long double)u1) + u1 * (long double)u3; } int main() { double y64,y80,u1,u2,u3; u1 = 0.025; u2 = 0.195; u3 […]