c# - .Net 中的往返格式说明符“R”失败
问题描述
文档建议我使用而G17
不是R
,因为R
有时无法往返。
但是,(1.0/10).ToString("G17")
给"0.10000000000000001"
,这是非常可怕的。而往返格式似乎工作得很好(并且给出了"0.1"
)。我很乐意花几个 cpu 周期来获得更美观的结果。但潜在的往返失败更令人担忧。
对于哪种(双)值确实R
无法往返?有多糟糕?.Net 版本(我们在 Net Framework 4.72 和 NetCore 3.1 上运行)会影响事情吗?在一个平台上写作和在另一个平台上阅读是否会使往返失败更加频繁?
我们正在考虑R
先写双打,解析检查往返,G17
只有在失败时才回退。有没有更好的方法来获得格式良好、可靠的结果?
解决方案
此处的往返行程是将数值转换为字符串,然后解析回相同的数值。
OP 对(1.0/10).ToString("G17") 的失望给出了“0.10000000000000001”,这非常可怕。是对往返成功的错误评估。中间字符串只是往返的一半。
Double
精确编码大约 2 64 个不同的值。所有可编码值都是一些有限的整数* 2 some_power。0.1不是其中之一。1.0/10 使数学商为 0.1,但值略有不同Double
。最接近的Double
值和它的两个最近的Double
邻居:
Before 0.099999999999999991673...
0.100000000000000005551...
After 0.100000000000000019428...
OP report 0.10000000000000001
Digit count 12345678901234567
OP的例子应该是 <(0.100000000000000005551).ToString("G17") 给出 "0.10000000000000001"> 这很好。
打印一个Double
withG17
提供 17 位有效数字,足以成功往返。
对于哪种(双)值,R 无法往返?有多糟糕?
为此,我继续记忆。 R
有时使用少于 17 个有效数字(如 15)来形成中间字符串。用于确定数字计数的算法有时会有点短,因此“某些情况下无法成功往返原始值”。
使用G17
总是有效的。对于某些值,小于 17 也可以。不利的一面G17
正是在这种情况下。少于 17 位数字就可以工作,并提供了一个更令人愉悦、更短的中间字符串。
令人愉悦的人类可读字符串不是往返的目标。目标是在Double
从值到字符串到值之后形成相同的形式,即使中间字符串在某些情况下有额外的数字。
有没有更好的方法来获得格式良好、可靠的结果?
“格式很好”是往返的额外负担。MS 尝试这样做R
但在某些情况下失败了,宁愿保留相同的损坏功能而不是修复它。
OP 会明智地避免该路径并放弃格式良好的中间字符串的目标,并专注于获取最终相同值的往返目标。
使用G17
.
我们正在考虑先将双精度写到 R,解析以检查往返,只有在失败时才回退到 G17。
如果做得正确,那将起作用。要评估正确性,请使用许多值测试您的代码,并将其和测试工具发布以进行代码审查。
推荐阅读
- twilio - How can you make Twilio Webchat a full screen window?
- reactjs - 运行 Cloud Build 时 GCP 引用格式无效
- kubernetes - 如何将 terraform 的输出传递到 Helm 子图
- javascript - 画廊搜索管道失败
- linux - 在bash中调用以base64解码的函数
- paypal - 我不明白如何获取令牌以进行 API 调用
- kubernetes - 在 Kubernetes 中运行 fail2ban?
- discord - 我试图让我的机器人给使用该命令的人一个角色,但它说“AttributeError:'tuple'对象没有属性'id'”
- python - 为什么 Beautiful Soup 找不到页面元素?
- c# - 如何在 C# 中访问 C:\Program Files\