Подсчитайте масштаб данного десятичного знака
Как я могу посчитать масштаб данного десятичного знака в Powershell?
$a = 0.0001
$b = 0.000001
Кастинг $a
к строке и возвращение $a.Length
дает результат 6... мне нужно 4.
Я думал, что будет десятичная или математическая функция, но я ее не нашел, и возиться со строкой кажется неэлегантным.
2 ответа
Вероятно, есть лучший математический способ, но я бы нашел такие десятичные знаки:
$a = 0.0001
$decimalPlaces = ("$a" -split '\.')[-1].TrimEnd('0').Length
По сути, разделите строку на .
и получите длину последней строки в массиве. Оберточная бумага$a
в двойных кавычках неявно вызывает .ToString()
с инвариантной культурой (вы можете расширить это как $a.ToString([CultureInfo]::InvariantCulture)
), что делает этот метод для определения количества десятичных знаков инвариантным для языка и региональных параметров.
.TrimEnd('0')
используется в случае $a
были получены из строки, а не из правильного числового типа, возможно, что в конце могут быть нули, которые не должны считаться десятичными знаками. Однако, если вам нужен масштаб, а не только используемые десятичные разряды, оставьте.TrimEnd('0')
выкл вот так:
$decimalPlaces = ("$a" -split '\.')[-1].Length
mclayton любезно связан с этим ответом на связанный вопрос C# в комментарии, и решение там действительно может быть адаптировано к PowerShell, если работает или преобразование в тип[decimal]
приемлемо:
# Define $a as a [decimal] literal (suffix 'd')
# This internally records the scale (number of decimal places) as specified.
$a = 0.0001d
# [decimal]::GetBits() allows extraction of the scale from the
# the internal representation:
[decimal]::GetBits($a)[-1] -shr 16 -band 0xFF # -> 4, the number of decimal places
В System.Decimal.GetBits
метод возвращает массив внутренних битовых полей, последний элемент которых содержит масштаб в битах 16–23 (8 бит, даже если максимально допустимый масштаб равен28
), что и было извлечено выше.
Примечание: PowerShell номер литерал, который является дробным числом безd
суффикс - например, 0.0001
становится [double]
Например, двоичное число с плавающей запятой двойной точности.
PowerShell автоматически конвертирует [double]
к [decimal]
значения по запросу, но обратите внимание, что могут быть ошибки округления из-за различных внутренних представлений, и что [double]
может хранить больше чисел, чем [decimal]
может (хотя и не совсем точно).
А [decimal]
буквальный - один с суффиксом d
(обратите внимание, что C# использует суффикс m
) - анализируется в масштабе точно так, как указано, так что применение вышеизложенного к0.000d
а также 0.010d
дает 3
в обоих случаях; то есть, хвостовые нули являются значимыми.
Это не применяется, если вы (неявно) конвертируете из[double]
примеры, такие как 0.000
а также 0.010
, для которого вышеприведенное дает 0
а также 2
соответственно.
Решение на основе строк:
Чтобы предложить более сжатую (также инвариантную к культуре) альтернативу полезному ответу Bender The Greatest:
$a = 0.0001
("$a" -replace '.+\.').Length # -> 4, the number of decimal places
Предостережение: это решение полагается на строковое представление по умолчанию для[double]
число, которое может не совпадать с исходным форматом ввода; например,.0100
, при последующем преобразовании в строку становится '0.01'
; однако, как обсуждалось выше, вы можете сохранить конечные нули, если начнете с[decimal]
буквальный: .0100d
преобразуется в '0.0100'
(введите количество десятичных знаков с сохранением).
"$a"
, Использует расширяемую строку (строка интерполяции PowerShell), чтобы создать культурно-инвариантным строковое представление числа с тем, чтобы гарантировать, что строковое представление использует.
как десятичный знак.По сути, PowerShell вызывает
$a.ToString([cultureinfo]::InvariantCulture)
за кулисами.[1].Напротив,
.ToString()
(без аргументов) применяет правила текущей культуры, а в некоторых культурах это,
- нет.
- используется как десятичный знак.Предупреждение: если вы используете только
$a
как LHS-replace
,$a
это неявно строковый, в этом случае вы - любопытно - получить с учетом культурного чувствительного поведением, как и.ToString()
- см. эту проблему на GitHub.
-replace '.+\.'
эффективно удаляет все символы до десятичной точки включительно из входной строки, и.Length
подсчитывает символы в полученной строке - количество десятичных знаков.
[1] Обратите внимание, что приведение типов строк в PowerShell также использует инвариантный язык и региональные параметры (по сути,::Parse($value, [cultureinfo]::InvariantCulture)
вызывается), так что для анализа строкового представления локальной культуры вам нужно будет использовать::Parse()
метод явно; например, [double]::Parse('1,2')
не [double] '1,2'
.