注意:这不是一个在做数学运算或比较时,浮标不精确的问题。这是关于格式化问题,虽然造成的混乱可能会泄漏在描述中。
背景:我们应用程序的日志条目实质上说19大于19。
复制:导致问题的数学步骤可以被发现,这个问题可以在一个简单的测试中重现:
[TestMethod]
public void WtfTest()
{
float bottom = -51;
float top = 19;
float rowHeight = (float)((top - bottom) / 3.0);
float line1 = bottom + rowHeight;
float line2 = line1 + rowHeight;
float line3 = line2 + rowHeight;
Assert.IsFalse(line3 > top, $"WTF: line3={line3:n50} is greater than top={top:n50}.");
}此测试失败,因为line3实际上大于top,可以使用BitConverter.GetBytes进行检查。这不是问题所在。真正的问题是失败消息,它完美地再现了原来的问题:
Assert.IsFalse失败。WTF: line3=19,00000000000000000000000000000000000000000000000000大于top=19,00000000000000000000000000000000000000000000000000.
你看:两个数字是完全相等的。尽管它们实际上不同。
其他发现:计算差异并格式化它会产生0,00000190734900000000000000000000000000000000000000,这似乎是正确的。
调试测试并查看VisualStudio的“局部变量”窗口中的值将显示19.0000019 for line3。
环境: Windows 10上的.Net Framework4.8,平台目标x64
最后一个问题:我如何才能得到正确的数字格式?
发布于 2022-11-04 08:28:26
根据文档,浮动的推荐格式是"G9“,而double的推荐格式是"G17”。
当与双值一起使用时,"G17“格式说明符确保原始的双值成功往返。这是因为Double是一个IEEE754-2008兼容的双精度(binary64)浮点数,它放弃了17位重要的精度数字。当与单个值一起使用时,"G9“格式说明符确保原始单个值成功往返。这是因为Single是一个IEEE754-2008兼容的单精度(binary32)浮点数,它放弃了9个重要的精度数字。
我在.net框架和.net内核上测试了以下代码
float bottom = -51;
float top = 19;
float rowHeight = (float)((top - bottom) / 3.0);
float line1 = bottom + rowHeight;
float line2 = line1 + rowHeight;
float line3 = line2 + rowHeight;
Console.WriteLine(line3.ToString("G9"));
Console.WriteLine(line3.ToString("N50"));这是结果
//.net framework
19.0000019
19.00000000000000000000000000000000000000000000000000
//.net core
19.0000019
19.00000190734863281250000000000000000000000000000000https://stackoverflow.com/questions/74313786
复制相似问题