Powershell - округление до ближайшего целого числа - PullRequest
25 голосов
/ 03 мая 2011

Как лучше всего округлить до ближайшего целого числа в Powershell?

Я пытаюсь [математика] :: усечь, но это не дает мне предсказуемые результаты.

Пример:

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

выводит 171 вместо ожидаемых 172!

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

выходы 172

Просто нужно что-то, что работает .... и должно всегда округляться (т. Е. round($myNum + 0.5) не будет работать из-за округления пекаря, которое может округляться, если число содержит 0,5)

С уважением Ted

Ответы [ 4 ]

30 голосов
/ 03 мая 2011

Ах, понятно. Похоже, тип данных должен быть десятичным:

[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

20 голосов
/ 03 мая 2011

Функция Math :: Floor в сочетании с объявлением [decimal] должна дать вам нужные результаты.

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

возвращает = 172

8 голосов
/ 13 ноября 2011

Проблема, с которой вы сталкиваетесь в исходном примере деления 17.2/0.1, связана с неточностью в представлении с плавающей запятой заданных десятичных значений (как упомянуто в комментарии Джои к другому ответу).Это можно увидеть в PowerShell, изучив представление в оба конца конечного значения:

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

Простой способ обойти это - объявить результат как int,поскольку PowerShell будет автоматически округлять результат до ближайшего целочисленного значения:

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

Обратите внимание, что при этом используется метод .NET по умолчанию MidpointRounding.ToEven (также известный как округление банкира).,Это имеет хорошие статистические свойства при табулировании большого числа числовых значений, но также может быть изменено на более простой метод от нуля:

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

Другой вариант - использовать более точное представление для исходных значений, что позволит полностью избежать этой проблемы:

PS> $bld = [decimal]17.2/0.1
PS> $bld.GetType().FullName
System.Decimal
PS> $bld.ToString()
172
4 голосов
/ 03 мая 2011

[Math]::floor($x) - встроенный способ сделать это.

Просто знайте, как он будет вести себя с отрицательными числами.[Math]::floor(5.5) возвращает 5, но [Math]::floor(-5.5) возвращает -6.

Если вам нужна функция для возврата значения, ближайшего к нулю, вам потребуется:

If ($x -ge 0) {
    [Math]::Floor($x)
} Else {
    [Math]::Ceiling($x)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...