使用以下代码,我得到结果" 4.31 43099"。
double f = atof("4.31");
long ff = f * 10000L;
std::cout << f << ' ' << ff << '\n';
如果我改变&#34;加倍f&#34;到&#34;浮动f&#34;。我得到了预期的结果&#34; 4.31 43100&#34;。我不确定是否要改变&#34; double&#34;到&#34;漂浮&#34;是一个很好的解决方案是否有任何好的解决方案可以确保我得到&#34; 43100&#34;?
答案 0 :(得分:3)
您无法消除浮点算术中的错误(尽管通过适当的分析可以计算出错误)。对于临时使用,你可以做的一件事是获得更直观的结果是将内置的float替换为整数转换(这会截断),并进行正常的舍入:
double f = atof("4.31");
long ff = std::round(f * 10000L);
std::cout << f << ' ' << ff << '\n';
这应输出您期望的内容:4.31 43100
使用10000L
也没有意义,因为无论你使用什么类型的整数类型,它仍会转换为f
的浮点类型进行乘法运算。只需使用std::round(f * 10000.0);
答案 1 :(得分:2)
问题在于,当谈到十进制数时,浮点本质上是不精确的。转换为二进制时,十进制数可以向上或向下舍入,具体取决于最接近的值。
在这种情况下,您只需要确保如果数字向下舍入,则会向上舍入。您可以通过向值添加尽可能少的数量来实现此目的,如果您使用C ++ 11,则使用nextafter
function完成:
long ff = std::nextafter(f, 1.1*f) * 10000L;
如果您没有nextafter
,则可以使用numeric_limits
进行近似。
long ff = (f * (1.0 + std::numeric_limits<double>::epsilon())) * 10000L;
我刚刚看到你的评论,你只使用4位小数,所以这会更简单但不那么健壮:
long ff = (f * 1.0000001) * 10000L;
答案 2 :(得分:0)
标准的C类型 - 我怀疑。
有许多值无法用这些位表示 - 它们实际上需要更多的空间来存储。所以浮点处理器只使用最接近的处理器。
浮动指向数字不能存储您认为可能的所有值 - 只有有限的位数 - 您不能在32位中存储超过40亿个不同的值。这只是第一个限制。
浮点值(以C表示)表示为:sign - one sign bit, power - bits which defines the power of two for the number, significand - the bits that actually make the number
。
您的实际号码是sign * significand * 2 inpowerof(power - normalization).
Double是1bit的符号,15位的幂(归一化为正,但不是点)和48位代表值;
很多但不足以代表所有的值,特别是当它们不能很容易地表示为两个幂的有限和时:像二进制1010.101101(101)。例如,它不能精确地表示像1/3 = 0.333333(3)这样的值。这是第二个限制。
尝试阅读 - 对浮点运算的优点和缺点的正确理解可能非常方便: http://en.wikipedia.org/wiki/Floating_point和http://homepage.cs.uiowa.edu/~atkinson/m170.dir/overton.pdf
答案 3 :(得分:0)
这里有一些困惑的答案!发生的事情是:4.31无法准确表示为单精度或双精度数。事实证明,最接近的可表示的单精度数字略大于4.31,而最接近的可表示的双精度数字略小于4.31。将浮点值赋给整数变量时,它会向零舍入(不是最接近的整数!)。
因此,如果f
是单精度,f * 10000L
大于43100,那么它会向下舍入到43100.如果f
是双精度,f * 10000L
小于43100,所以它向下舍入到43099。
上午的评论。建议f * 10000L + 0.5
,这是我认为最好的解决方案。