双精度乘以整数精度

multiplication of double with integer precision

本文关键字:精度 整数 双精度      更新时间:2023-10-16

我有一个 3.4 的双精度。但是,当我将其乘以 100 时,它得到 339 而不是 340。似乎是由双精度引起的。我该如何解决这个问题?

谢谢

首先发生了什么:

  1. 3.4 不能完全表示为二进制分数。因此,实现选择可表示的最接近的二进制分数。我不确定它是否总是四舍五入到零,但在您的情况下,所代表的数字确实较小。
  2. 转换为整数 truncates,即使用具有较小绝对值的最接近的整数。
  3. 由于两次转化都偏向于同一方向,因此您总是会出现舍入误差。

现在你需要知道你想要什么,但你可能想使用对称舍入,即找到最接近的整数,无论是更小还是更大。这可以实现为

#include <cmath>
int round(double x) { std::floor(x + 0.5); } // floor is provided, round not

int round(double x) { return x < 0 ? x - 0.5 : x + 0.5; }

我不完全确定它确实四舍五入到零,所以如果您使用它,请验证后面。

如果您需要完全精度,您可能需要使用 Boost.Rational .

您可以使用两个整数并将小数部分乘以乘数/10。

例如

int d[2] = {3,4};
int n = (d[0] * 100) + (d[1] * 10);

如果你真的想要小数点两侧的所有精度。确实取决于应用程序。

点值很少精确。遗憾的是,当浮点值转换为 C 中的整数时,该值将四舍五入为零。这意味着,如果您有 339.999999,则强制转换的结果将是 339。

为了克服这个问题,您可以从值中添加(或减去)"0.5"。在本例中,339.99999 + 0.5 => 340.499999 => 340(转换为 int 时)。

或者,您可以使用标准库提供的众多转换函数之一。

您没有值为 3.4 的

双精度值,因为 3.4 不是可表示为双精度(至少在普通机器上,并且大多数异国情调也是如此)。 你拥有的是一些价值非常接近 3.4。 乘法后,你有一些价值非常接近340。 但肯定不是399。

你在哪里看到399? 我猜你只是强制转换为int,使用static_cast,因为此操作截断为零。 其他操作可能会做什么您需要:以固定格式输出,在十进制,例如,舍入(在定义的实现中方式,但我知道的所有实现都使用圆到偶数默认情况下);函数round舍入到最近,舍入在中途情况下远离零(但您的结果不会接近中途的任何地方)。 这是在 中使用的舍入商业应用。

真正的问题是你在做什么,需要一个确切的积分值。 根据应用的不同,可能会更多适合使用intlong,将实际值缩放为必要(即存储实际值的 100 倍,或无论如何),或某种十进制算术包,而不是比使用double.