计算给定小数的比例
Count the scale of a given decimal
如何计算 Powershell 中给定小数的小数位数?
$a = 0.0001
$b = 0.000001
将 $a
转换为字符串并返回 $a.Length
结果为 6...我需要 4。
我以为会有小数或数学函数,但我没有找到它,而且乱用字符串似乎很不雅。
可能有更好的数学方法,但我会这样找到小数位:
$a = 0.0001
$decimalPlaces = ("$a" -split '\.')[-1].TrimEnd('0').Length
基本上,在 .
字符处拆分字符串并获取数组中最后一个字符串的长度。将 $a
包裹在双引号中隐式调用具有不变区域性的 .ToString()
(您可以将其扩展为 $a.ToString([CultureInfo]::InvariantCulture)
),使此方法确定小数位数区域性不变。
.TrimEnd('0')
用于万一 $a
来自字符串,而不是正确的数字类型,可能包含不应计为小数位的尾随零。但是,如果您想要 scale 而不仅仅是使用的小数位,请将 .TrimEnd('0')
关闭,如下所示:
$decimalPlaces = ("$a" -split '\.')[-1].Length
mclayton helpfully linked to 在评论中,那里的解决方案确实可以适应 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
method returns 一个内部位字段数组,其最后一个元素包含位 16 - 23 中的比例(8 位,即使允许的最大比例是28
),也就是上面提取的内容。
注意:PowerShell 数字文字是小数 ,没有 d
后缀 - 例如,0.0001
成为 [double]
实例,即双精度二进制浮点数。
PowerShell 根据需要自动将 [double]
转换为 [decimal]
值,但请注意,由于内部表示不同,可能存在舍入误差,并且 [double]
可以存储更大的数字比 [decimal]
可以(虽然不准确)。
A [decimal]
文字 - 后缀 d
(注意 C# 使用后缀 m
) - 是 以 完全按照指定 的比例进行解析,因此将上述内容应用于 0.000d
和 0.010d
在这两种情况下都会产生 3
;也就是说,尾随零 有意义。
如果您(隐含地)从 0.000
和 0.010
等 [double]
实例转换,这 不 适用,上面分别产生 0
和 2
。
基于字符串的解决方案:
提供比 更简洁(也是文化不变的)替代方案:
$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
作为 -replace
的 LHS,$a
是 隐式 字符串化,在这种情况下,你 - 奇怪地 - 获得文化 - 敏感 行为,如 .ToString()
- 见 this GitHub issue.
-replace '.+\.'
有效地从输入字符串中删除包括小数点在内的所有字符,并且 .Length
计算结果字符串中的字符 - 小数位数.
[1] 请注意,PowerShell 中来自字符串的 casts 也使用不变区域性(实际上,调用了 ::Parse($value, [cultureinfo]::InvariantCulture)
),以便按顺序要解析 culture-local 字符串表示,您需要显式使用 ::Parse()
方法;例如,[double]::Parse('1,2')
,而不是 [double] '1,2'
。
如何计算 Powershell 中给定小数的小数位数?
$a = 0.0001
$b = 0.000001
将 $a
转换为字符串并返回 $a.Length
结果为 6...我需要 4。
我以为会有小数或数学函数,但我没有找到它,而且乱用字符串似乎很不雅。
可能有更好的数学方法,但我会这样找到小数位:
$a = 0.0001
$decimalPlaces = ("$a" -split '\.')[-1].TrimEnd('0').Length
基本上,在 .
字符处拆分字符串并获取数组中最后一个字符串的长度。将 $a
包裹在双引号中隐式调用具有不变区域性的 .ToString()
(您可以将其扩展为 $a.ToString([CultureInfo]::InvariantCulture)
),使此方法确定小数位数区域性不变。
.TrimEnd('0')
用于万一 $a
来自字符串,而不是正确的数字类型,可能包含不应计为小数位的尾随零。但是,如果您想要 scale 而不仅仅是使用的小数位,请将 .TrimEnd('0')
关闭,如下所示:
$decimalPlaces = ("$a" -split '\.')[-1].Length
mclayton helpfully linked to [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
method returns 一个内部位字段数组,其最后一个元素包含位 16 - 23 中的比例(8 位,即使允许的最大比例是28
),也就是上面提取的内容。
注意:PowerShell 数字文字是小数 ,没有 d
后缀 - 例如,0.0001
成为 [double]
实例,即双精度二进制浮点数。
PowerShell 根据需要自动将 [double]
转换为 [decimal]
值,但请注意,由于内部表示不同,可能存在舍入误差,并且 [double]
可以存储更大的数字比 [decimal]
可以(虽然不准确)。
A [decimal]
文字 - 后缀 d
(注意 C# 使用后缀 m
) - 是 以 完全按照指定 的比例进行解析,因此将上述内容应用于 0.000d
和 0.010d
在这两种情况下都会产生 3
;也就是说,尾随零 有意义。
如果您(隐含地)从 0.000
和 0.010
等 [double]
实例转换,这 不 适用,上面分别产生 0
和 2
。
基于字符串的解决方案:
提供比
$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
作为-replace
的 LHS,$a
是 隐式 字符串化,在这种情况下,你 - 奇怪地 - 获得文化 - 敏感 行为,如.ToString()
- 见 this GitHub issue.
-replace '.+\.'
有效地从输入字符串中删除包括小数点在内的所有字符,并且.Length
计算结果字符串中的字符 - 小数位数.
[1] 请注意,PowerShell 中来自字符串的 casts 也使用不变区域性(实际上,调用了 ::Parse($value, [cultureinfo]::InvariantCulture)
),以便按顺序要解析 culture-local 字符串表示,您需要显式使用 ::Parse()
方法;例如,[double]::Parse('1,2')
,而不是 [double] '1,2'
。