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]
может (хотя и не точно).
A[decimal]
буквально - вклe с суффиксом d
(обратите внимание, что в C # используется суффикс m
) - анализируется со шкалой в точности так, как указано , так что применение выше к 0.000d
и 0.010d
дает 3
в обоих случаях;то есть конечные нули являются значимыми .
Это не применяется, если вы (неявно) конвертируете из [double]
экземпляров, таких как0.000
и 0.010
, для которых приведенное выше дает 0
и 2
соответственно.
A строка решение на основе :
Чтобы предложить более краткую (также культурно-инвариантную) альтернативу Полезный ответ Бендера Величайшего :
$a = 0.0001
("$a" -replace '.+\.').Length # -> 4, the number of decimal places
Предостережение : Это решениеполагается на строковое представление по умолчанию числа [double]
, которое не обязательно должно соответствовать исходному формату ввода;например, .0100
, если позже будет преобразовано в строку, становится '0.01'
;однако, как обсуждалось выше, вы можете сохранить конечные нули, если начнете с литерала [decimal]
: .0100d
преобразуется в '0.0100'
(сохранено количество введенных десятичных знаков).
"$a"
, использует расширяемую строку (строковая интерполяция PowerShell) для создания культурально-инвариантного строкового представления числа, чтобы гарантировать, что строковое представление использует .
в качестве десятичного числаmark.
По сути, PowerShell вызывает $a.ToString([cultureinfo]::InvariantCulture)
за кулисами. [1] .
Для контраста, .ToString()
(без аргументов) применяет правила текущей культуры , а в некоторых культурах в качестве десятичной отметки используется ,
- не .
-
Предостережение : Если вы используете просто $a
в качестве LHS -replace
, $a
является неявно стратифицированным, в этом случае вы - с любопытством- получить культуру- чувствительное поведение, как с .ToString()
- см. этот выпуск GitHub .
-replace '.+\.'
эффективно удаляет все символы до и включая десятичную точку из входной строки, а .Length
подсчитывает символы в результирующей строке - количество десятичных знаков.
[1] Обратите внимание, что откачивает из строк в PowerShell, также используют инвариантную культуру (фактически, вызывается ::Parse($value, [cultureinfo]::InvariantCulture)
), так что длядля разбора строкового представления culture-local вам необходимо явно использовать метод ::Parse()
;например, [double]::Parse('1,2')
, а не [double] '1,2'
.