提问人:Gabe Stotler 提问时间:7/20/2023 最后编辑:phuclvGabe Stotler 更新时间:7/21/2023 访问量:45
Powershell 中点舍入
Powershell Midpoint Rounding
问:
我正在构建一个 API,而我使用的系统只在 PowerShell 中使用中点舍入。我发现某些数字仍然不遵守这一规则,我对原因的研究被证明是徒劳的。基本上,任何低于 5 四舍五入的东西,以及任何高于 5 四舍五入的东西,除了我猜的某些情况?
如果有人愿意提供帮助,我的脚本包含在这张图片中。
11.025 = 11.03
12.025 = 12.03
29.025 = 29.03
39.025 = 39.03
此值和脚本中的所有内容都是预期的,但以下情况除外:
19.025 = 19.02
如果有人能解释发生了什么,那将不胜感激。
答:
我正在使用 [float] 变量,我所看到的关于舍入问题的所有内容都是关于 [float] 变量的。我改用 [decimal],这清除了一切。我猜 [float] 中有一些位有时会禁止它使用 MidpointRounding 四舍五入。
评论
[double]
[float]
(1.0).GetType().FullName
在 PowerShell 中,浮点文字的类型为 ,在双精度中最接近 19.025 的是 19.0249999999999985789...比 19.03 更接近 19.02。因此,结果符合预期。[double]
事实上,大多数十进制值不会完全存储在二进制浮点数中。如果您不知道这一点,请查看浮点数学坏了吗?。不可能将值存储为有限的非重复二进制小数值。您可以通过打印更多数字轻松检查
PS $> 11.025, 12.025, 19.015, 19.025, 29.025, 39.025 |% { $_.ToString("G60") }
11.0250000000000003552713678800500929355621337890625
12.0250000000000003552713678800500929355621337890625
19.0150000000000005684341886080801486968994140625
19.02499999999999857891452847979962825775146484375
29.02499999999999857891452847979962825775146484375
39.02499999999999857891452847979962825775146484375
没有什么可以阻止中点舍入工作,只是因为数字并不完全是 5。如果要处理精确的十进制值,则必须使用该类型。但是您必须直接使用后缀 (like ) 初始化值或将字符串转换为 .不要从 [double
] 转换为 [decimal]
,因为这不会给你丢失的精度,就像 . 可能导致四舍五入的值为 19.02499999999999985789...不知何故,它在这种情况下起作用,可能是因为 shell 直接从文字构造为字符串,但它并非在所有情况下都起作用,例如[decimal]
d
19.025d
[decimal]"19.025"
[decimal]double_literal
[decimal]([double]double_literal)
[decimal]19.025
[double]
[decimal]
PS $> [decimal]19.0255555555555555555555555555
19.0255555555556
PS $> [decimal]19.02555555555555e25
190255555555556000000000000
评论
[decimal]
19.25
[double]
([decimal] 19.0249999999999985789).ToString('N20')
[decimal]
评论
ToPositiveInfinity