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