Ответ 1
А, я вижу. Похоже, что тип данных должен быть десятичным:
[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
Какой лучший способ округлить до ближайшего целого числа в Powershell?
Я пытаюсь [math]:: truncate, но это не дает мне прогнозируемых результатов.
Пример:
$bla = 17.2/0.1
[math]::truncate($bla)
выводит 171 вместо ожидаемых 172!
$bla = 172
[math]::truncate($bla)
выходы 172
Просто нужно что-то, что работает... и должно всегда округлить (т.е. round($myNum + 0.5)
не будет работать из-за округления заклинания, которое может округлить, если число имеет 0,5 компонента)
Отношения Ted
А, я вижу. Похоже, что тип данных должен быть десятичным:
[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
Функция Math:: Floor в сочетании с объявлением [decimal] должна дать вам нужные результаты.
[Math]::Floor([decimal](17.27975/0.1))
возвращает = 172
Проблема, с которой вы сталкиваетесь с оригинальным примером деления 17.2/0.1
, связана с неточностями в представлении с плавающей запятой заданных десятичных значений (как указано в Joey comment на другой ответ). Вы можете увидеть это в 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
[Math]::floor($x)
- это встроенный способ сделать это.
Просто знайте, как он будет вести себя с отрицательными числами. [Math]::floor(5.5)
возвращает 5
, но [Math]::floor(-5.5)
возвращает -6
.
Если вам нужна функция, чтобы вернуть значение, самое близкое к нулю, вам понадобится:
If ($x -ge 0) {
[Math]::Floor($x)
} Else {
[Math]::Ceiling($x)
}