从 .NET Framework 4.7.2 移植到 .NET5.0 后如何避免“-0”作为 double.ToString() 结果?
How to avoid "-0" as double.ToString() result after porting from .NET Framework 4.7.2 to .NET5.0?
我正在将 .NET Framework 4.7.2 Visual Studio 项目移植到 .NET5.0,当值为负且接近于零时,我遇到了 double.ToString 的不同行为。
例如,双精度值 -7.1054273576010019E-15 转换为字符串时 returns "-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 或扩展方法并根据需要转换 double 但这需要更改代码中的每个转换,而且任何从事该项目的开发人员都需要在未来。在我看来,这个解决方案不是很直观,很可能是错误的来源。
有没有办法更轻松地恢复以前的行为?
Microsoft 是否愿意在 .NET 的未来版本中更改此设置?
编辑:
我在这里的讨论中问了同样的问题 https://github.com/dotnet/runtime/discussions/54537
如果它对其他人有帮助。
从链接 post 看来,做出更改似乎是为了更加符合 IEEE 754,这是所有语言都试图遵守的行为,以尽量减少混淆 - 或者至少标准化一种特殊形式的混淆。
如果这些更改变得过于向后不兼容并破坏了人们的程序,他们总是有可能恢复这些更改,但如果此时还没有完成(它已经在 .NET Core 3.1 中,这是LTS 版本,在 .NET 5 中)我认为不会。但是这里问“微软愿意改变这个”是错误的地方-file an issue in dotnet/runtime直接问微软
解决方法需要遍及所有地方,但也很简单:将“-0”替换为“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") is "-0" in .NET Core and "0" in .NET Framework
被标记为重复的:
我正在将 .NET Framework 4.7.2 Visual Studio 项目移植到 .NET5.0,当值为负且接近于零时,我遇到了 double.ToString 的不同行为。
例如,双精度值 -7.1054273576010019E-15 转换为字符串时 returns "-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 或扩展方法并根据需要转换 double 但这需要更改代码中的每个转换,而且任何从事该项目的开发人员都需要在未来。在我看来,这个解决方案不是很直观,很可能是错误的来源。
有没有办法更轻松地恢复以前的行为? Microsoft 是否愿意在 .NET 的未来版本中更改此设置?
编辑: 我在这里的讨论中问了同样的问题 https://github.com/dotnet/runtime/discussions/54537 如果它对其他人有帮助。
从链接 post 看来,做出更改似乎是为了更加符合 IEEE 754,这是所有语言都试图遵守的行为,以尽量减少混淆 - 或者至少标准化一种特殊形式的混淆。
如果这些更改变得过于向后不兼容并破坏了人们的程序,他们总是有可能恢复这些更改,但如果此时还没有完成(它已经在 .NET Core 3.1 中,这是LTS 版本,在 .NET 5 中)我认为不会。但是这里问“微软愿意改变这个”是错误的地方-file an issue in dotnet/runtime直接问微软
解决方法需要遍及所有地方,但也很简单:将“-0”替换为“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") is "-0" in .NET Core and "0" in .NET Framework
被标记为重复的: