首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#浮点格式的怪癖

C#浮点格式的怪癖
EN

Stack Overflow用户
提问于 2022-11-04 07:58:23
回答 1查看 48关注 0票数 2

注意:这不是一个在做数学运算或比较时,浮标不精确的问题。这是关于格式化问题,虽然造成的混乱可能会泄漏在描述中。

背景:我们应用程序的日志条目实质上说19大于19

复制:导致问题的数学步骤可以被发现,这个问题可以在一个简单的测试中重现:

代码语言:javascript
复制
[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

最后一个问题:我如何才能得到正确的数字格式?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-04 08:28:26

根据文档,浮动的推荐格式是"G9“,而double的推荐格式是"G17”。

当与双值一起使用时,"G17“格式说明符确保原始的双值成功往返。这是因为Double是一个IEEE754-2008兼容的双精度(binary64)浮点数,它放弃了17位重要的精度数字。当与单个值一起使用时,"G9“格式说明符确保原始单个值成功往返。这是因为Single是一个IEEE754-2008兼容的单精度(binary32)浮点数,它放弃了9个重要的精度数字。

我在.net框架和.net内核上测试了以下代码

代码语言:javascript
复制
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"));

这是结果

代码语言:javascript
复制
//.net framework
19.0000019
19.00000000000000000000000000000000000000000000000000

//.net core
19.0000019
19.00000190734863281250000000000000000000000000000000
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74313786

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档