8

假设我们有以下简单的代码

        string number = "93389.429999999993";
        double numberAsDouble = Convert.ToDouble(number);
        Console.WriteLine(numberAsDouble);

之后该转换numberAsDouble变量的值为 93389.43。我该怎么做才能使这个变量保持完整的数字而不四舍五入?我发现它Convert.ToDecimal的行为方式不同,但我需要将值设为双倍。

-------------------小更新---------------------

在上述代码的第 2 行放置断点表明 numberAsDouble 变量在显示在控制台之前具有舍入值 93389.43。

4

7 回答 7

11

93389.429999999993不能完全表示64 位浮点数。Adouble只能容纳 15 或 16 位数字,而您有 17 位数字。如果您需要该级别的精度,请改用 a decimal

(我知道你说你需要它作为双重,但如果你能解释为什么,可能有替代解决方案)

于 2013-01-15T17:51:21.630 回答
6

这是预期的行为。

双精度数不能准确地表示每个数字。这与字符串转换无关。

你可以自己检查一下:

Console.WriteLine(93389.429999999993);

这将打印93389.43.

以下也显示了这一点:

Console.WriteLine(93389.429999999993 == 93389.43);

这打印True

于 2013-01-15T17:47:52.323 回答
4

请记住,这里有两个转换。首先,您将字符串转换为双精度,然后将该双精度转换回字符串以显示它。

您还需要考虑 adouble没有无限精度;根据字符串的不同,某些数据可能会因为 double 没有能力存储而丢失。

当转换为双精度时,它不会比它必须的更“四舍五入”。考虑到双精度数的能力,它将创建最接近所提供数字的双精度数。当将该双精度转换为字符串时,更有可能不保留某些信息。

于 2013-01-15T17:48:37.797 回答
3

请参阅以下内容(特别是 Michael Borgwardt 回答的第一部分):

十进制与双倍!- 我应该使用哪一个以及何时使用?

根据您尝试转换的数字,双精度并不总是保持精度

如果您需要精确,则需要使用decimal

于 2013-01-15T17:50:22.230 回答
0

这是对 adouble可以存储的精度的限制。您可以通过尝试转换3389.429999999993来自己看到这一点。

于 2013-01-15T17:50:24.140 回答
0

double类型具有 64 位的有限精度,因此当实数存储在 numberAsDouble 变量中时会出现舍入错误。

适用于您的示例的解决方案是decimal改用具有 128 位精度的类型。然而,同样的问题出现在较小的差异。

对于任意大数,System.Numerics.BigInteger.NET Framework 4.0 中的对象支持整数的任意精度。但是,您将需要一个 3rd 方库来使用任意大实数。

于 2013-01-15T18:04:02.773 回答
0

您可以将小数位截断为您需要的位数,不超过双精度。

例如,这将截断到小数点后 5 位,得到 93389.42999。只需将 100000 替换为所需的值

string number = "93389.429999999993";
decimal numberAsDecimal = Convert.ToDecimal(number);
var numberAsDouble = ((double)((long)(numberAsDecimal * 100000.0m))) / 100000.0;
于 2013-01-15T18:07:50.347 回答