C++ 如何避免C+;中的浮点数舍入问题+;?

C++ 如何避免C+;中的浮点数舍入问题+;?,c++,floating-point,floating-point-conversion,C++,Floating Point,Floating Point Conversion,使用下面的代码,我得到结果“4.3143099” double f=atof(“4.31”); 长ff=f*10000L; std::不能使用标准C类型-我怀疑 有许多值不能用这些位来表示——它们实际上需要更多的存储空间。因此,浮点处理器只使用尽可能接近的值 浮点数字不能存储您认为可以存储的所有值-只有有限的位数-您不能在32位中放置超过40亿个不同的值。这只是第一个限制 浮点值(在C中)表示为:符号-一个符号位,幂-定义数字的二次幂的位,有效位-实际构成数字的位 您的实际数字是POWEROF(

使用下面的代码,我得到结果“4.3143099”

double f=atof(“4.31”);
长ff=f*10000L;

std::不能使用标准C类型-我怀疑

有许多值不能用这些位来表示——它们实际上需要更多的存储空间。因此,浮点处理器只使用尽可能接近的值

浮点数字不能存储您认为可以存储的所有值-只有有限的位数-您不能在32位中放置超过40亿个不同的值。这只是第一个限制

浮点值(在C中)表示为:
符号-一个符号位,幂-定义数字的二次幂的位,有效位-实际构成数字的位

您的实际数字是POWEROF(电源-标准化)中的符号*有效位*2。

Double是1位符号,15位幂(标准化为正,但不是点),48位表示值

表示所有值虽然很多,但还不够,特别是当它们不能很容易地表示为二的有限幂和时:比如二进制1010.101101(101)。例如,它不能精确地表示像1/3=0.333333(3)这样的值。这是第二个限制

试着阅读-充分理解浮点运算的优缺点可能非常方便:

使用标准C类型-我怀疑

有许多值不能用这些位来表示——它们实际上需要更多的存储空间。因此,浮点处理器只使用尽可能接近的值

浮点数字不能存储您认为可以存储的所有值-只有有限的位数-您不能在32位中放置超过40亿个不同的值。这只是第一个限制

浮点值(在C中)表示为:
符号-一个符号位,幂-定义数字的二次幂的位,有效位-实际构成数字的位

您的实际数字是POWEROF(电源-标准化)中的符号*有效位*2。

Double是1位符号,15位幂(标准化为正,但不是点),48位表示值

表示所有值虽然很多,但还不够,特别是当它们不能很容易地表示为二的有限幂和时:比如二进制1010.101101(101)。例如,它不能精确地表示像1/3=0.333333(3)这样的值。这是第二个限制

试着阅读-充分理解浮点运算的优缺点可能非常方便:
问题是,当谈到十进制数时,浮点本质上是不精确的。十进制数在转换为二进制时可以向上或向下舍入,具体取决于最接近的值

在这种情况下,您只需要确保如果数字向下舍入,则改为向上舍入。您可以通过向该值添加尽可能小的量来完成此操作,如果您有C++11:

long ff = std::nextafter(f, 1.1*f) * 10000L;
如果您没有
nextafter
,可以使用近似值


问题是,当谈到十进制数时,浮点本质上是不精确的。十进制数在转换为二进制时可以向上或向下舍入,具体取决于最接近的值

在这种情况下,您只需要确保如果数字向下舍入,则改为向上舍入。您可以通过向该值添加尽可能小的量来完成此操作,如果您有C++11:

long ff = std::nextafter(f, 1.1*f) * 10000L;
如果您没有
nextafter
,可以使用近似值


这里有一些困惑的答案!发生的情况是:4.31不能准确地表示为单精度或双精度数字。结果表明,最近的可表示单精度数略大于4.31,而最近的可表示双精度数略小于4.31。将浮点值赋给整型变量时,它将向零舍入(而不是向最接近的整数舍入!)

因此,如果
f
为单精度,
f*10000L
大于43100,则四舍五入为43100。如果
f
是双精度,
f*10000L
小于43100,则四舍五入为43099


n.m.的评论建议
f*10000L+0.5
,这是我认为最好的解决方案。

这里有一些令人困惑的答案!发生的情况是:4.31不能准确地表示为单精度或双精度数字。结果表明,最近的可表示单精度数略大于4.31,而最近的可表示双精度数略小于4.31。将浮点值赋给整型变量时,它将向零舍入(而不是向最接近的整数舍入!)

因此,如果
f
为单精度,
f*10000L
大于43100,则四舍五入为43100。如果
f
是双精度,
f*10000L
小于43100,则四舍五入为43099


n.m.的评论建议
f*10000L+0.5
,我认为这是最好的解决方案。

您无法消除浮点算术中的错误(尽管通过适当的分析,您可以计算错误)。对于随意使用,要获得更直观的结果,可以做的一件事是将内置的浮点到整数转换(进行截断)替换为正常舍入:

double f = atof("4.31");
long ff = std::round(f * 10000L);
std::cout << f << ' ' << ff << '\n';
double f=atof(“4.31”);
长ff=标准:圆形(f*10000L);

std::cout您将无法消除浮点算术中的错误(尽管通过适当的分析,您可以计算错误)。对于随意使用,您可以对ge做一件事
long ff = (f * 1.0000001) * 10000L;
double f = atof("4.31");
long ff = std::round(f * 10000L);
std::cout << f << ' ' << ff << '\n';