2011-05-03 48 views
21

¿Cuál es la mejor manera de redondear al número entero más cercano en Powershell?Powershell - Redondee al número entero más cercano

Estoy intentando [matemáticamente] truncar pero no me está dando resultados predecibles.

Ejemplo:

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

salidas 171 en lugar del 172 espera!

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

salidas 172

Sólo necesitan algo que funciona .... y siempre deben redondear hacia abajo (es decir round($myNum + 0.5) no funcionará debido al redondeo de panadero que puede redondear hacia arriba si el número tiene un componente 0.5)

Saludos Ted

Respuesta

17

La Matemáticas :: función del suelo combinado con la declaración [decimal] debe darle los resultados que desea.

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

vuelve = 172

+0

hablado demasiado pronto ... [matemáticas] :: piso (17,2/0,1) da salida a 171, necesito esto para dar salida 172. – ted

+0

extraño ... ¿Por qué? – Louis

+1

@Louis: Debido a que los números de punto flotante no pueden representar '17.2' y' 0.1' exactamente, es por eso que está obteniendo errores de redondeo en los últimos lugares y por lo tanto un resultado * cerca de *, pero no exactamente 172. – Joey

2

[Math]::floor($x) es la forma integrada de hacerlo.

Simplemente tenga en cuenta cómo se comportará con los números negativos. [Math]::floor(5.5) devuelve 5, pero [Math]::floor(-5.5) devuelve -6.

Si necesita la función para devolver el valor más cercano a cero, tendrá que:

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

Para devolver el valor más cercano a cero puede usar '[Math] :: Truncate'. – Joey

7

El problema que está teniendo con el ejemplo original de 17.2/0.1 división se debe a inexactitud en la representación de coma flotante de los valores decimales dados (como se mencionó en Joey's comment en otra respuesta). Esto se puede ver en PowerShell mediante el examen de la round-trip representation del valor final:

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

Una forma sencilla de evitar esto es declarar el resultado como int, como PowerShell redondeará automáticamente a la el resultado al entero más cercano valor:

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

Tenga en cuenta que este utiliza el método predeterminado de .NET MidpointRounding.ToEven (también conocido como el banquero de redondeo).Esto tiene buenas propiedades estadísticas al tabular gran número de valores numéricos, pero también se puede cambiar a la más simple lejos de cero método:

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 

Otra opción es utilizar una representación más precisa de los valores originales, que evitará el problema en su totalidad:

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