Powershell - Round down to nearest whole number

2020-05-24 20:26发布

问题:

What's the best way to round down to nearest whole number in Powershell?

I am trying [math]::truncate but its not giving me predictable results.

Example:

$bla = 17.2/0.1
[math]::truncate($bla) 

outputs 171 instead of the expected 172!

$bla = 172
[math]::truncate($bla) 

outputs 172

Just need something that works.... and must always round down (i.e round($myNum + 0.5) won't work due to baker's rounding which may round up if the number has a 0.5 component)

Regards ted

回答1:

Ah, I see. Looks like the datatype needs to be decimal:

[decimal] $de = 17.2/.1
[double] $db = 17.2/.1

[math]::floor($de)
172
[math]::floor($db)
171

http://msdn.microsoft.com/en-us/library/system.math.floor(v=vs.85).aspx



回答2:

The Math::Floor function combined with [decimal] declaration should give you the results you want.

[Math]::Floor([decimal](17.27975/0.1))

returns = 172



回答3:

The issue you are encountering with the original 17.2/0.1 division example is due to inaccuracy in the floating-point representation of the given decimal values (as mentioned in Joey's comment on another answer). You can see this in PowerShell by examining the round-trip representation of the final value:

PS> $bla = 17.2/0.1
PS> $bla.GetType().FullName
System.Double
PS> $bla.ToString()
172
PS> $bla.ToString('r')
171.99999999999997

A simple way to get around this is to declare the result as int, as PowerShell will automatically round to the the result to the nearest integer value:

PS> [int]$bli = 17.2/0.1
PS> $bli.GetType().FullName
System.Int32
PS> $bli.ToString()
172

Note that this uses the default .NET method of MidpointRounding.ToEven (also known as banker's rounding). This has nice statistical properties when tabulating large numbers of numeric values, but can also be changed to the simpler away-from-zero method:

function round( $value, [MidpointRounding]$mode = 'AwayFromZero' ) {
  [Math]::Round( $value, $mode )
}

PS> [int]3.5
4
PS> [int]4.5
4
PS> round 3.5
4
PS> round 4.5
5

Another option is to use a more accurate representation for the original values, which will avoid the issue entirely:

PS> $bld = [decimal]17.2/0.1
PS> $bld.GetType().FullName
System.Decimal
PS> $bld.ToString()
172


回答4:

[Math]::floor($x) is the built-in way to do it.

Just be aware of how it will behave with negative numbers. [Math]::floor(5.5) returns 5, but [Math]::floor(-5.5) returns -6.

If you need the function to return the value closest to zero, you'll need:

If ($x -ge 0) {
    [Math]::Floor($x)
} Else {
    [Math]::Ceiling($x)
}


标签: powershell