【发布时间】:2013-05-01 16:42:07
【问题描述】:
我有一个输入浮点值,它是 0.0f
当将此值乘以更大的范围时,浮点精度自然会降低,这意味着该值可能会超出等效范围。
例如,如果我从以下值开始:
0.99999983534521f
再乘以100,得到:
100.000000000000f
这很好,但是我如何将浮点表示减少为仍然小于 100 的最接近的浮点值?
我发现了这个手动小技巧:
union test
{
int integer;
float floating;
};
test value;
value.floating = 1.0f;
printf("%x\n", value.integer);
然后我取那个十六进制值并将它减少一个十六进制数字,然后像这样明确地设置它:
unsigned int almost_one = 0x3f7fffff;
float value = 1.0f;
if (value >= 1.0f) std::memcpy(&value, &almost_one, sizeof(float));
这对于这个特定值很有效,但是我可以使用更通用的方法吗?
我希望有一个我不知道的魔法指令可以用来实现这一目标!
编辑:这里有一组很棒的答案,std::nextafter 看起来像我所追求的。不幸的是,我还不能使用 C++11 数学库,所以这对我不起作用。为了避免复杂的事情,我将用 C++11 标记这个问题,并在下面接受 Mike 的回答。
我为 C++03 提出了一个新问题:Alternative to C++11's std::nextafter and std::nexttoward for C++03?
【问题讨论】:
-
这看起来像是未定义的行为......
-
你想达到什么目的?如果您的结果正好是 100.0f,那么这是最接近实际结果的数字。将尾数减一只会使您的结果不那么准确。
-
你从
0.99999983534521f得到 100.0,因为它实际上是 1.0,因为那里有足够的 9 和 8 来翻转它 - 它的准确度并不低,这正是数字的限制是(如果你打印原始数字,你会得到 1.0,因为这是它的值)。请记住,浮点数只有 24 位尾数,以十进制形式给出大约 7 位有效数字。乘以一个数字不会降低其精度。浮点数在加减较大数字时会丢失精度,因为数字必须归一化[小数点在同一位置]。 -
@MatsPetersson:不,最接近 0.99999983534521 的 IEEE-754 32 位二进制浮点值是 0.999999821186065673828125,在您到达 1 之前还有两个。
-
@MatsPetersson:我没有看到 Pascal Cuoq 说问题中描述的问题不会发生。他写道
x*M > M不可能是真的。但是,问题是x*M == M可能是真的。
标签: c++ c++11 floating-point floating-accuracy