Powershell 中点舍入

Powershell Midpoint Rounding

提问人:Gabe Stotler 提问时间:7/20/2023 最后编辑:phuclvGabe Stotler 更新时间:7/21/2023 访问量:45

问:

我正在构建一个 API,而我使用的系统只在 PowerShell 中使用中点舍入。我发现某些数字仍然不遵守这一规则,我对原因的研究被证明是徒劳的。基本上,任何低于 5 四舍五入的东西,以及任何高于 5 四舍五入的东西,除了我猜的某些情况?

如果有人愿意提供帮助,我的脚本包含在这张图片中。

My Scripts

11.025 = 11.03
12.025 = 12.03
29.025 = 29.03
39.025 = 39.03

此值和脚本中的所有内容都是预期的,但以下情况除外:

19.025 = 19.02

如果有人能解释发生了什么,那将不胜感激。

PowerShell 浮点 舍入误差 银行家舍入

评论

1赞 Santiago Squarzon 7/20/2023
听起来你在寻找ToPositiveInfinity
1赞 phuclv 7/21/2023
为什么我不应该上传代码/数据/错误的图像?复制控制台文本并以正确的格式粘贴到此处

答:

0赞 Gabe Stotler 7/20/2023 #1

我正在使用 [float] 变量,我所看到的关于舍入问题的所有内容都是关于 [float] 变量的。我改用 [decimal],这清除了一切。我猜 [float] 中有一些位有时会禁止它使用 MidpointRounding 四舍五入。

评论

0赞 mklement0 7/20/2023
顺便说一句:PowerShell 的浮点数文本成为实例,而不是 .验证方式[double][float](1.0).GetType().FullName
1赞 phuclv 7/21/2023 #2

在 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]d19.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

评论

0赞 mklement0 7/21/2023
我不认为 PowerShell 从字符串文字的字符串表示形式构造实例。我不清楚确切的转换机制,但是作为 ,它是定期四舍五入到最接近的十进制表示,大概会发生,这不是这个数字的中点四舍五入,正如你所看到的那样。但是,您从数字文字开始的建议是合理的。[decimal]19.25[double]([decimal] 19.0249999999999985789).ToString('N20')[decimal]