我正在使用不同版本的 .NET 尝试此代码块:
using System;
using System.Linq;
public class Program
{
public static void Main()
{
Decimal decimalVal = 9.38M;
Double doubleVal = 9.38;
Single singleVal = 9.38F;
Int32 i = 100;
Console.WriteLine(decimalVal*i); // "938.00"
Console.WriteLine(doubleVal*i); // .NET Core+: "938.0000000000001". .NET Framework 4.7.2: "938"
Console.WriteLine(singleVal*i); // "938"
var doubleResult = doubleVal*i;
var doubleBytes = BitConverter.GetBytes(doubleResult);
var str = string.Join(" ", doubleBytes.Select(x => Convert.ToString(x, 2).PadLeft(8, '0')));
Console.WriteLine(str);
// Same value for .NET Core+ and .NET Framework 4.7.2:
// 00000001 00000000 00000000 00000000 00000000 01010000 10001101 01000000
Console.WriteLine(BitConverter.IsLittleEndian); // "True", in case it's important to know?
}
}
为什么
9.38*100
在 .NET Framework 4.7.2 中生成准确的 938
值,但在 .NET Core 3.1 及更高版本中,它生成 938.0000000000001
?
我查看了用于表示数字的实际位,无论使用哪个 .NET 版本,这些位都是相同的。
顺便说一句,差异可能早于 .NET Core 3.1 开始,但我只测试了 https://dotnetfiddle.net 上可用的内容。
这并不是乘法结果的变化。这是默认字符串格式的更改 - 使生成的字符串能够更准确地表示结果。
这是代码的另一个版本,这次使用我的 DoubleConverter 代码以十进制形式显示 double
的
精确值:
using System;
class Program
{
static void Main()
{
double initial = 9.38;
double actualResult = initial * 100;
double literal1 = 938.0000000000001;
double literal2 = 938;
Console.WriteLine($"Actual result ToString: {actualResult}");
Console.WriteLine($"Actual result exact value: {DoubleConverter.ToExactString(actualResult)}");
Console.WriteLine($"Equal to literal 938.0000000000001? {actualResult == literal1}");
Console.WriteLine($"Equal to literal 938? {actualResult == literal2}");
}
}
.NET 8.0 的结果:
ctual result ToString: 938.0000000000001
Actual result exact value: 938.0000000000001136868377216160297393798828125
Equal to literal 938.0000000000001? True
Equal to literal 938? False
.NET 4.8 的结果:
Actual result ToString: 938
Actual result exact value: 938.0000000000001136868377216160297393798828125
Equal to literal 938.0000000000001? True
Equal to literal 938? False
在我看来,.NET 8.0 结果更好 - 基本上,如果您采用 ToString
的
output,并将其用作代码中的
double
文字,您最终会得到与乘法的结果。对于 .NET 4.8 来说并非如此。