- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
昨天我问了一个question关于为什么我在浮点运算中失去准确性。我收到了关于中间结果如何保存在 x87 寄存器中的答案。这很有帮助,但一些细节仍然在逃避我。这是我在上一个问题中提供的程序的变体,我在 Debug模式下使用 VC++ 2010 Express。
int main()
{
double x = 1.8939201459282359e-308; /* subnormal number */
double tiny = 4.9406564584124654e-324; /* smallest IEEE double */
double scale = 1.6;
double temp = scale*tiny;
printf("%23.16e\n", x + temp);
printf("%23.16e\n", x + scale*tiny);
}
这输出
1.8939201459282369e-308
1.8939201459282364e-308
根据 IEEE 标准,第一个值是正确的。为 scale
变量赋予 2.0 的值可为两种计算提供正确的值。我知道第一次计算中的 temp
是一个低于正常值的值,因此会失去精度。我还了解到 scale*tiny
的值保存在 x87 寄存器中,该寄存器具有更大的指数范围,因此该值比 temp
更精确。我不明白的是,当将值添加到 x
时,我们从较低精度的值中得到了正确的答案。当然,如果精度较低的值可以给出正确答案,那么精度较高的值也应该给出正确答案吗?这与“双舍入”有关吗?
提前致谢,这对我来说是一个全新的主题,所以我有点挣扎。
最佳答案
关键是由于指数范围较大,这两个数字在 x87 表示中不是次正规的。
在 IEEE754 表示中,
x = 0.d9e66553db96f × 2^(-1022)
tiny = 0.0000000000001 × 2^(-1022)
但在 x87 表示中,
x = 1.b3cccaa7b72de × 2^(-1023)
tiny = 1.0000000000000 × 2^(-1074)
现在,当在 IEEE754 表示中计算 1.6*tiny
时,它会四舍五入为 0.0000000000002 × 2^(-1022)
,因为这是最接近的可表示数字数学结果。将其添加到 x
结果是
0.d9e66553db96f × 2^(-1022)
+ 0.0000000000002 × 2^(-1022)
-----------------------------
0.d9e66553db971 × 2^(-1022)
但是在 x87 表示中,1.6*tiny
变成了
1.999999999999a × 2^(-1074)
什么时候添加
1.b3cccaa7b72de × 2^(-1023)
+ 0.0000000000003333333333334 × 2^(-1023)
-----------------------------------------
1.b3cccaa7b72e1333333333334 × 2^(-1023)
四舍五入到 53 位有效位的结果是
1.b3cccaa7b72e1 × 2^(-1023)
尾数为 1 的最后一位。如果将其转换为 IEEE754 表示形式(尾数最多可以有 52 位,因为它是次正规数),因为它恰好位于两个相邻可表示数之间的一半0.d9e66553db970 × 2^(-1022)
和 0.d9e66553db971 × 2^(-1022)
默认情况下四舍五入到尾数为零的最后一位.
请注意,如果 FPU 未配置为仅使用 53 位作为尾数,而是 x87 扩展精度类型的全 64 位,则加法的结果将更接近 IEEE754 结果 0.d9e66553db971 × 2^(-1022)
并因此四舍五入。
实际上,由于 x87 表示具有更大的指数范围,因此与 IEEE754 表示相比,IEEE754 次正规数的尾数有更多的位数,即使尾数中的位数有限。因此,这里的计算结果在 x87 中比在 IEEE754 中多了一位有效位。
关于c - 再次浮点精度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15450918/
关于这个话题已经说了很多,但是我找不到我的问题的确切答案。 JavaScript 无法准确表示 0.1 等小数,这是可以理解的。 例如,由于乘法运算期间发生舍入误差,这是正确的: 0.1 * 3 ==
在 zig 中,可以使用“{d}”以十进制表示法打印浮点值。这将自动以全精度打印该值。有没有办法指定位数?是针对每个值,还是作为某种全局设置? 最佳答案 这将限制小数点后的位数,四舍五入和零填充: f
我正在进行的项目需要高精度。减法时我遇到的问题在这里说明: >> 1-0.9999999999999999 ans = 1.1102e-16 >> 1-0.99999999999999999 ans
是否可以使变量本身的精度成为将在运行时定义的变量? 说,如果我尝试编译: SUBROUTINE FOO( VARIABLE, PRECISION_VALUE ) IMPLICI
我正在查询 SQLite 数据库以获取纬度/经度详细信息。 SELECT * FROM tblMain where latitude > -33.866 and latitude 151.20
我一直使用下划线将整数定义为 Fortran 中的特定类型。 下面是一段代码,用于演示 1_8 的含义,例如: program main implicit none integer(2)
我正在寻找一种方法来告诉 pint 要打印多少个有效数字。例如,当我输入以下内容时: import pint ureg = pint.UnitRegistry() print(3*ureg.m /9)
我正在从事一个项目,目标是从山上追踪动物。在第一个实地考察季中,我们使用了 OpenTags 和经过校准的摄像头,虽然可以正常工作,但需要大量的处理/校准,而且至关重要的是,当系统出现问题时无法提供任
在 JavaScript 中有没有一种方法可以确定一个数除以另一个数是否会得到整数?就像 18.4/0.002 给我们 9200,但是 18.4/0.1 给我们 183.99999999999997。
我正在尝试使用 Big.js 在 javascript 中完成此计算 r = (a * b)/ sqrt( ( a*sin(θ) )^2 + ( b*cos(θ) )^2 ) 我也试过 math.js
我有这个片段着色器代码,它在 iOS 模拟器(非视网膜)和 iPad2(非视网膜)之间显示不同: highp vec2 textCoord; textCoord.x = gl_Fr
这个问题在这里已经有了答案: C++ calculating more precise than double or long double (2 个答案) 关闭 6 年前。 是否有任何浮点类型在小
我似乎一直困惑的三个问题: 为什么代码是 x & ~077比这行代码 x & 0177700 更好。是因为精度损失较小吗? 为什么此代码对于设置数字中的第 5 位不正确? num = num + 0x
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Precision of Floating Point 我正在尝试使用一些 float 来计算概率,但我的最
由于微 Controller 的精度,我定义了一个包含两个 float 比率的符号,而不是直接写结果。 #define INTERVAL (0.01F/0.499F) 代替 #defi
我试图比较这 3 种搜索算法,起初我使用 time.h 库但没有任何反应,输出始终是 0.00000 秒。现在我试图在循环中使用一些计数器。但我在这里也有问题, 任何人都可以帮我处理代码吗? 这是我的
char buf[10]; int counter, x = 0; snprintf (buf, sizeof buf , "%.100d%n", x, &counter); printf("Coun
我注意到在评估向量时对我来说是不可预测的行为。直接执行它与在循环中进行索引似乎是完全不同的。谁能帮我解决这个问题?我知道可能在它如何进行每个操作中都有解释,所以我需要一些关于如何查找它的键 多谢指教提
我想在我的应用程序中使用精确的 gps 定位。所以我遵循了一个简单的教程(LocationManager 的基本用法,明确要求 GPS 提供商,要求更新 0 ms,0 m)并创建了一个应用程序。我对更
float 在 1.0f 和 0.0f 之间有多少位精度,这样每个值都可以唯一表示? 例如,如果第一个小数 float 不能表示 0.13f,答案就是 float 只有一位精度。 最佳答案 std::
我是一名优秀的程序员,十分优秀!