在我的代码中尝试查找错误一小时后,我终于找到了原因。我试图在1f添加一个非常小的浮点数,但没有发生任何事情。在试图弄清楚为什么我发现将小浮点数加到0f时效果很好。
为什么会这样? 这与“数量级”有关吗? 这个问题有解决办法吗?
提前致谢。
编辑:
目前不能选择更改为双精度或小数。
答案 0 :(得分:21)
因为单精度(32位)浮点值的精度在小数点后大约7位数。这意味着您添加的值基本上为零,至少在添加到1
时。然而,值本身可以毫不费力地存储在浮点数中,因为在这种情况下指数很小。但要成功将其添加到1
,您必须使用较大数字的指数...然后零点后的数字将在舍入中消失。
如果您需要更高的精确度,可以使用double
。在性能方面,这不应该对今天的硬件和内存产生影响通常也不会像你必须考虑每个变量那样受到限制。
编辑:正如您所述,使用double
不是一个选项,您可以使用Kahan summation,而不是评论中指出的akuhn。
另一种选择可能是以双精度执行中间计算,然后再次投射到float
。但是,这只会在有更多操作时帮助,而不仅仅是向较大的数字添加一个非常小的数字。
答案 1 :(得分:7)
答案 2 :(得分:4)
这可能是因为float中精度的位数是常数,但指数显然可以变化。
这意味着虽然你可以将你的小数字添加到0,但你不能期望将它添加到指数与0不同的数字,因为没有足够的精度数字。
您应该阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic。
答案 3 :(得分:3)
看起来它与浮点精度有关。如果我是你,我会使用其他类型,例如decimal
。这应该可以解决精度错误。
答案 4 :(得分:3)
使用float
,您只能获得约七位数的精确度。所以你的数字将四舍五入为1f。如果您想存储此类号码,请改用double
答案 5 :(得分:3)
除了接受的答案:如果您需要总结许多小数字和一些较大数字,您应该使用Kahan Summation 。
答案 6 :(得分:2)
如果性能问题(因为您无法使用double
),那么binary scaling/fixed-point可能是一个选项。 float
被存储为整数,但是被大量缩放(例如,2 ^ 16)。中间算术是用(相对快速的)整数运算完成的。最后的答案可以通过除以比例因子转换回最后的浮点数。
如果目标处理器缺少硬件浮点单元,通常会这样做。
答案 7 :(得分:0)
你在你的文字上使用f后缀,这将使这些浮点数而不是双打。因此,你的小浮子将在较大的浮子中消失。