PowerShell 中点四舍五入

huangapple go评论86阅读模式
英文:

Powershell Midpoint Rounding

问题

我正在构建一个API,而我使用的系统只在PowerShell中使用中点舍入。我发现某些数字仍然违反了这个规则,我的研究为什么会这样已经毫无结果。基本上,小于5的四舍五入到下一个数,而大于5的四舍五入到上一个数,除了某些情况?

我的脚本包含在这个图片中,如果有人想要帮助。

PowerShell 中点四舍五入

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

这些值以及脚本中的所有内容都是预期的,除了:

19.025 = 19.02

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

英文:

I am building an API and the system that I am using just uses midpoint rounding in PowerShell. I've come to find out that certain numbers still disobey this rule and my research as to why has proven futile. Basically, anything below 5 rounds down, and anything above 5 rounds up, except for certain situations I guess?

My scripts are included in this image if anybody would like to assist.

PowerShell 中点四舍五入

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

This values and everything in the script is expected EXCEPT for:

19.025 = 19.02

If somebody could explain what is going on that would be greatly appreciated.

答案1

得分: 1

在PowerShell中,浮点字面值的类型是[double],而在双精度中最接近19.025的值是19.0249999999999985789...,这更接近19.02而不是19.03。因此,结果如预期所示。

实际上,大多数十进制值在二进制浮点中不会以精确的方式存储。如果你不知道这一点,请查看 https://stackoverflow.com/q/588004/995714。无法将你的值存储为有限的非重复的二进制分数值。你可以通过打印更多的小数位数来轻松检查这一点。

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。如果你想处理精确的十进制值,你必须使用[decimal]类型。但是你必须直接使用d后缀初始化该值(例如19.025d)或者将其从字符串转换为[decimal]"19.025"不要从[double]转换为[decimal],因为这不会让你恢复丢失的精度,[decimal]double_literal被执行为[decimal]([double]double_literal)[decimal]19.025可能会导致值被四舍五入为[double],其值为19.0249999999999985789... 在这种情况下它可以工作,可能是因为shell直接从字符串文字构造了[decimal],但它不会在所有情况下工作,例如

PS $> [decimal]19.0255555555555555555555555555
19.0255555555556
PS $> [decimal]19.02555555555555e25
190255555555556000000000000
英文:

In PowerShell floating-point literals are of type [double], and the closest to 19.025 in double precision is 19.0249999999999985789... which is closer to 19.02 than 19.03. Therefore the result is as expected.

In fact most decimal values won't be stored exactly in binary floating-point. If you're not aware of that please check out https://stackoverflow.com/q/588004/995714. It's impossible to store your values as finite non-repeating binary fractional values. You can check that easily by printing more digits

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

There is nothing that prevents midpoint rounding from working, it's just because the digit isn't exactly 5. If you want to deal with exact decimal values you must use the [decimal] type. But you'll have to initialize the value directly with the d suffix (like 19.025d) or convert from string as [decimal]"19.025". Don't cast from [double] to [decimal] because that won't give you the lost precision back, [decimal]double_literal is done as [decimal]([double]double_literal). [decimal]19.025 can result in the value rounded to [double] which is 19.0249999999999985789... Somehow it works in that case, probably because the shell constructs the [decimal] directly from the literal as string, but it won't work in all cases, for example

PS $> [decimal]19.0255555555555555555555555555
19.0255555555556
PS $> [decimal]19.02555555555555e25
190255555555556000000000000

答案2

得分: 0

我正在使用[float]变量,关于舍入问题的所有内容都是关于[float]变量的。相反,我转换为[decimal],这样一切都清晰了。我猜测[float]中的某些位有时会阻止它使用MidpointRounding进行四舍五入。

英文:

I am using [float] variables, everything I have seen about rounding issues has been about [float] variables. I casted to [decimal] instead, and that cleared everything up. I guess there are bits in a [float] that sometimes prohibit it from rounding with MidpointRounding.

huangapple
  • 本文由 发表于 2023年7月20日 22:41:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/76731036.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定