从 .NET Framework 4.7.2 移植到 .NET5.0 后如何避免“-0”作为 double.ToString() 结果?

问题描述 投票:0回答:3

我正在将 .NET Framework 4.7.2 Visual Studio 项目移植到 .NET5.0,当值为负且接近于零时,我遇到了 double.ToString 的不同行为。

例如,双精度值 -7.1054273576010019E-15 在转换为字符串时会返回“-0”,即使我在转换之前对其进行舍入,而使用 .NET Framework 4.7.2 时,其结果是“0”(相同的代码)。

这里讨论了这种差异https://devblogs.microsoft.com/dotnet/floating-point-parsing-and-formatting-improvements-in-net-core-3-0/但我不太同意正如标题所述,这是一个改进,我相信 0 不应该有符号,它既不是正数也不是负数。

我知道我可以创建自定义 IFormatProvider 或扩展方法并根据需要转换双精度值,但这需要对代码中的每次转换进行更改,并且从事该项目的任何开发人员将来都需要使用它。在我看来,这个解决方案不是很直观,而且很可能是错误的根源。

有没有一种方法可以更轻松地恢复以前的行为? Microsoft 愿意在未来版本的 .NET 中改变这一点吗?

编辑: 我在这里的讨论中问了同样的问题https://github.com/dotnet/runtime/discussions/54537 如果对其他人有帮助的话。

c# .net double tostring .net-5
3个回答
1
投票

从链接的帖子来看,似乎进行了更改是为了更符合 IEEE 754,这是所有语言都试图遵守的行为,以最大程度地减少混乱 - 或者至少标准化特定形式的混乱。

如果这些更改变得过于向后不兼容并大量破坏人们的程序,他们总是有可能会恢复这些更改,但如果此时尚未完成(它已经在 .NET Core 3.1 中,这是一个 LTS 版本,在 .NET 5 中)我认为不会。但在这里询问“微软是否愿意改变这一点”是错误的地方 - 在 dotnet/runtime 中提交问题并直接询问微软。

解决方法需要无处不在,但也很简单:将确切的字符串“-0”替换为“0”(例如,替换子字符串“-0”可能会导致-0.5的符号反转)。


0
投票

Math.Abs
会将负零(您可以通过舍入或其他方式获得)和正零映射到 零。

因此,您可以使用

"-0"
,而不是将
"0"
替换为
Abs
作为字符串。

但也许你也可以这样做:

if (rounded == 0.0) {
    rounded = 0.0;  // POSITIVE zero
}

这应该将两种类型的零映射到正零。

在表达式内部,可以写为

rounded == 0.0 ? 0.0 : rounded

很清楚如何为

double
编写扩展方法,它将统一两种类型的零(并保持所有其他
double
值不变)。

相关问题在这里:

-0.1.ToString("0") 在 .NET Core 中为“-0”,在 .NET Framework 中为“0”

其被标记为以下内容的重复项:

.net core 3 产生与版本 2.2 不同的浮点结果


0
投票

我发现三节自定义数字格式在 .NET Framework 和 .NET 5+ 中的工作方式相同。 如果您能够添加格式参数,它可以用作解决方法。

Debug.Assert("0" == (-0.0).ToString("0.###;-0.###;0"));

// alternative forms:
Debug.Assert("0" == $"{-0.0:0.###;-0.###;0}");
Debug.Assert("0" == string.Format("{0:0.###;-0.###;0}", -0.0));
© www.soinside.com 2019 - 2024. All rights reserved.