C/C++: 浮点数算术题
如果一个浮点数反复乘以一个小于一的数,浮点数是否有可能变为零?
这是一个示例:
float number = 1.0f;
for ( int i = 0; i < ONE_BILLION; ++i )
{
number *= 0.01f;
}
但请不要将您的答案限制在示例中。
谢谢!
If a float is repeatedly multiplied by a number that is less than one, is it plausible that the the float could become zero?
Here is an example:
float number = 1.0f;
for ( int i = 0; i < ONE_BILLION; ++i )
{
number *= 0.01f;
}
But please don't limit your answer to the example.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
是的,当乘法的结果小于最接近零的可表示数时,它就会变成零。对于 IEEE 浮点,任何小于或等于
0.5f
(但大于零)的乘数都会发生这种情况;但是,如果乘数稍大于0.5f
(例如,0.5f + FLT_EPSILON
),结果将收敛到最小的可表示正数并永远保持该值。比较使用和不使用-DGREATER
时该程序的行为:Yes, when the result of the multiplication would be smaller than the representable number closest to zero, it will become zero. With IEEE floating point, this will happen for any multiplier less than or equal to
0.5f
(but greater than zero); however, if the multiplier is even slightly larger than0.5f
(for instance,0.5f + FLT_EPSILON
) the result will converge to the smallest representable positive number and stay there forever. Compare the behavior of this program with and without-DGREATER
:取决于实施。使用典型的 IEEE 754 实现,您将首先陷入非规格化(失去精度),然后捕捉到 0。但其他一些实现可能会给您带来浮点下溢错误、爆炸崩溃。
干杯&呵呵,
Depends on the implementation. With typical IEEE 754 implementation you'll first get down into denormals (losing precision) and then snap to 0. But some other implementation may give you a floating point underflow error, bang crash.
Cheers & hth.,
它取决于相乘值和当前舍入模式。考虑这个例子:
编辑: @Pascal:在我的计算机上,这个用 GCC 编译的简单示例:
收敛到
6.93643e-044
,而不是零。我的观点是,如果中间计算的精度高于最终结果(最常见的例子是 x87 80 位内部 FP 寄存器),并且最终结果被截断为
float
,那么你肯定会得零分。但如果计算是在浮点数上执行的,那么你根本无法保证它们会收敛到零。 这里是一些不错的读物。对于一般情况,最好的(而且更快)的解决方案是将循环转换为带有对数的简单表达式:
这将输出:
It depends on the multiplied value and on the current rounding mode. Consider this example:
EDIT: @Pascal: on my computer, this simple example compiled with GCC:
converges to
6.93643e-044
, and not to zero.My point is that if the intermideate calculations are performed with larger precision than the final result (the most common example is x87 80bit internal FP register), and at the end the result is truncated to
float
, then you'll get a zero for sure. But if the calculations are peformed on float, then you have no garanty at all that they will converge to zero. Here is some good reading.For general case, the best (and much faster) solution would be to transform the loop to a simple expression with logarithms:
that will output:
是的。最终你会得到一个小于最小可表示正浮点数的数字,该数字将下溢到零。
Yes. Eventually you'll reach a number less than the smallest representable positive float, which will underflow to zero.
我感到惊讶的是,很少有人指出一个简单的事实,即当您低于/高于最小/最大可表示(绝对)非零/非无限值时,您将得到下溢/上溢异常,这将停止执行。这是因为,一个非零数(例如)乘以另一个非零数可能会变成零,就像简单地通过尺度中的某个点就可能变成无穷大一样,这在数学上是不正确的。
当然,您可以屏蔽 FP 控制字中的异常,并接受您的程序在数学上的行为不正确,并最终传递一个零,您可以将其插入除法并得到另一个异常。
在我看来,控制 FP 处理要好得多。我遇到过一些组织,他们将整数数学留给 fp 以“简化编程”,但最终得到的处理背景只是他们模糊地理解,以及所谓的“奇怪”结果和异常,而他们绝对不知道。
I'm surprised that so few pointed out the simple fact that when you go below/above the smallest/largest representable (absolute) non-zero/non-infinite value you will get an underflow/overflow exception which will halt execution. This is because it is mathematically incorrect that a non-zero number (for example) multiplied by a another non-zero number could become zero in the same way that it could become infinity simply by passing a certain point in the scale.
Of course you can mask out the exception(s) in the FP control word and accept that your program behaves mathematically incorrect and eventually deliver a zero which you might plug into a division and get another exception.
In my view it is much better to have control over the FP-processing. I have encountered organizations where they've left integer math for fp to "simplify programming" but have ended up with a processing background which they only vaguely understand and so-called "strange" results and exceptions which they definitely don't.