概述转换为科学
记数法时出现双
精度误差 @H_301_0@我正在构build一个程序来将双精度值转换为科学值格式(尾数,指数)。 然后我注意到下面@H_301_0@369.7900000000000 -> 3.6978999999999997428 68600000 -> 6.8599999999999994316@H_301_0@我也注意到了其他几个值的相同模式。 最大分数误差是@H_301_0@0.000 000 000 000 001 = 1*e-15@H_301_0@我知道在计算机中代表双精度值的不准确性。 这可以得出结论:我们得到的最大分数误差是1*e-15 ? 什么是重要的呢?@H_301_0@我经历了堆栈溢出中浮点精度问题的大部分问题,但是我没有看到有关64位的最大分数误差的问题。@H_301_0@为了清楚我做的计算,我也提到了我的代码片段@H_301_0@double norm = 68600000; if (norm) { while (norm >= 10.0) { norm /= 10.0; exp++; } while (norm < 1.0) { norm *= 10.0; exp--; } }@H_301_0@现在我明白了@H_301_0@norm = 6.8599999999999994316; exp = 7@H_301_0@您得到的数字与double数据类型的机器epsilon有关。@H_301_0@一个double是64位长,1位为符号,11位为指数,52位为尾数部分。 double的价值是由@H_301_0@1.mmmmm... * (2^exp)@H_301_0@由于尾数只有52位,所以当加到1.0时,任何低于2^-52 double值都会完全丢失,因为它的意义小。 在二进制中, 1.0 + 2^-52就是@H_301_0@1.000...00 + 0.000...01 = 1.000.....01@H_301_0@显然,任何更低的值都不会改变1.0的值。 你可以自己验证一个程序中的1.0 + 2^-53 == 1.0 。@H_301_0@这个数字2^-52 = 2.22e-16被称为机器epsilon,并且是一个浮点运算期间出现的相对误差的上界,因为具有double值的舍入误差。@H_301_0@同样, float的尾数为23位,所以它的机器epsilon是2^-23 = 1.19e-7 。@H_301_0@你得到1e-15的原因可能是因为当你执行许多算术运算时积累的错误,但我不能说,因为我不知道你正在做的确切的计算。@H_301_0@编辑 :我已经看着你的问题68600000相对错误。@H_301_0@首先,您可能有兴趣知道,如果您将步骤分解为四舍五入错误,则可能会改变您的计算结果:@H_301_0@686.0/10.0 = 68.59999999999999431566 686.0/10.0/10.0 = 6.85999999999999943157 686.0/100.0 = 6.86000000000000031974@H_301_0@在第一行中,最接近68.6的double低于实际值,但在第三行中,我们看到最接近6.86的double 。@H_301_0@如果我们看看程序的绝对错误 e_abs = abs(v-v_approx) ,我们看到它是@H_301_0@6.8600000 - 6.85999999999999943156581139192 ~= 5.684e-16@H_301_0@然而, 相对误差 e_abs = abs( (v-v_approx)/ v) = abs(e_abs/v)将是@H_301_0@5.684e-16 / 6.86 ~= 8.286e-17@H_301_0@这确实低于我们的2.22e-16机器epsilon。@H_301_0@如果你想知道关于浮点运算的所有细节, 这是一篇你可以阅读的着名论文。 总结
以上是内存溢出为你收集整理的转换为科学记数法时出现双精度误差全部内容,希望文章能够帮你解决转换为科学记数法时出现双精度误差所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
评论列表(0条)