Powershell:将分数转换为整数 - 令人惊讶的舍入行为

时间:2018-02-19 10:40:03

标签: powershell integer rounding bankers-rounding

关于带小数的整数,我有一个有趣的问题。

假设我执行以下操作:

[int] $a = 5/2
$a

我已经尝试了10次以确保,并且powershell始终返回2

有没有办法强制Powershell在这种情况下向上或向下舍入,默认情况下是否设置为向下舍入?

我假设依赖于机器和Powershell环境,我可能在某些点上获得3,在其他点上获得2。

2 个答案:

答案 0 :(得分:6)

[Math]::Floor($a) --> 2
[Math]::Ceiling($a)--> 3
[Math]::Round($a) --> 2

Floor将为您提供前面的整数,Ceiling将提供后续的整数。 但是如果你想要使用Round函数将其四舍五入,它将遵循中点舍入(中点舍入在历史上远离零),如下所示 -

[Math]::Round(2.50) --> 2
[Math]::Round(2.51) --> 3
[Math]::Round(2.49) --> 2
[math]::Round(2.50,[System.MidpointRounding]::AwayFromZero) --> 3
[math]::Round(2.49,[System.MidpointRounding]::AwayFromZero) --> 2
[math]::Round(2.51,[System.MidpointRounding]::AwayFromZero) --> 3

您可以根据需要使用任一功能。

答案 1 :(得分:5)

Vivek Kumar's answer很有帮助,但有一些令人困惑的方面。

通常,将小数转换为整数总是涉及舍入的形式;在投射隐式转换的上下文中,编程语言通常使用 rounding to the nearest integer 的形式。 特殊注意事项适用于数字的模糊情况,其小数部分正好是.5 多个策略存在 - 并且不同的编程语言采用不同的策略。

在构建PowerShell的 .NET Framework 的上下文中,这些策略的总括术语 中点舍入 ,为简便起见,下面使用的具体策略名称将中点(.5)称为 half (以下示例使用PowerShell语法,但适用于所有 .NET语言)。

  • 投放[int] 使用 half- to-even 舍入,其中小数部分.5的数字四舍五入为最接近的偶数整数(无论是正数还是负数):

    • [int] 2.5 - > 2(!)情境向下 - 周围,因为整数部分恰好是甚至且正面
    • [int] 3.5 - > 4情境 up -rounding
    • 此舍入策略也适用于隐式转换为PowerShell有时执行的整数类型 - 请参阅上一节。
    • PowerShell 语法陷阱:强制转型的优先级高于/,因此[int] 5/2 不按预期工作;使用[int] (5/2)
  • 控制中点舍入行为,请使用 .NET [Math] class' Round()方法

    • 使用 [int] [Math]::Round($number, [MidpointRounding]::AwayFromZero) 获取 half-远离零舍入(数字小于{ {1}}舍入到最接近的整数,其绝对更大)。

      • .5 - > [Math]::Round(2.5, [MidpointRounding]::AwayFromZero)
      • 3 - > [Math]::Round(-2.5, [MidpointRounding]::AwayFromZero)
      • 注意:-3方法(通常)返回[Math],因此您可能必须将结果转换为[double](或不同的整数类型)才能获得真整数。

请注意,[int]不仅提供 - 整数舍入,还提供特定数量的小数位数;例如,
[Math]::Round()会产生[Math]::Round(2.55, 1, [MidpointRounding]::AwayFromZero)谢谢,Ansgar Wiechers

其他形式的舍入:小数部分(2.6除外)的特定值无关的那些:

  • 使用 0 转向四舍五入(删除小数部分):

    • [Math]::Truncate($number) - > [Math]::Truncate(2.1);同上22.5,例如
    • 2.9 - > [Math]::Truncate(-2.1)
  • 使用 -2 向正无限舍入(向上舍入到最近的大于或等于整数):

    • [Math]::Ceiling($number) - > [Math]::Ceiling(2.1)
    • 3 - > [Math]::Ceiling(-2.1)(!)
  • 使用 -2 转向负无穷大四舍五入(向下舍入到最近的小于等于整数):

    • [int] [Math]::Floor($number) - > [Math]::Floor(2.1)
    • 2 - > [Math]::Floor(-2.1)(!)

可选进一步阅读:

执行隐式转换的PowerShell示例,其中使用了此策略:

-3会产生数组1..(2.5),因为范围运算符表达式1, 2的端点被强制转换为2.5 [int],因此表达式为与2

有效相同

由于PowerShell构建于.NET Framework之上,因此最终会调用[Convert]::ToInt32()

可能令人惊讶的圆形半到甚至策略背后的意图是在对四舍五入的数字进行求和时最小化预期误差",according to Wikipedia。 / p>

维基百科关于四舍五入的页面上有一节rounding functions across programming languages

与.NET相比, JavaScript 例如使用 half-up 舍入(1..2 - > Math.round(2.5),{{ 1}} - > 3) - .NET甚至不提供的中点舍入模式。