如何在PowerShell中将类似于5.7303333333e+02的字符串转换为十进制数?

6
我想将类似于5.7303333333e+02的字符串转换为decimal类型。我尝试使用[decimal] :: TryParse,但返回值为false。
是否有类似于[datetime] :: parseexact的方法或任何简洁的方法可以转换这些字符串?或者我必须解析出e + 02并单独执行该数学运算吗?
2个回答

9

关于:

[int]"5.7303333333e+02"
[decimal]"5.7303333333e+02"

1
+1 它可以工作。但我想知道后台使用的转换机制是什么,如果不是 [decimal]::TryParse("5,7303333333e+02", [ref] $dec)。问题在于不支持科学计数法,因为 [decimal]::TryParse("5,7303333333", [ref] $dec) 可以工作... 请参见:http://msdn.microsoft.com/en-us/library/9zbda557.aspx - Davor Josipovic
我很惊讶这个方法起作用了,但 [decimal]::TryParse 却没有。不过,使用它比起使用 TryParse 看起来更简洁。 - rtf
4
通过使用“Trace-Command TypeConversion { [decimal]'5.7303333333e+02' } -PSHost”命令,您可以看到PowerShell捕获了格式异常并通过解析为“[double]”,然后转换为“[decimal]”来重新尝试转换。 - Emperor XLII
这段代码无法运行。[decimal]'5.730333333333333333333333333e+02' 将返回一个不正确的值。 - phuclv

0

简而言之:

在使用ParseTryParse时,您需要指定NumberStyles.Float

<i>PS C:\></i> $s = '5.7303333333333333333333333e+02'
<i>PS C:\></i> <b>$style = [Globalization.NumberStyles]::Float</b>
<i>PS C:\></i> $culture = [cultureinfo]::GetCultureInfo('en-US')
<i>PS C:\></i> <b>[decimal]::Parse($s, $style)</b>
573.03333333333333333333333
<i>PS C:\></i> [decimal]$dec = 0
<i>PS C:\></i> <b>[decimal]::TryParse($s, $style, $culture, [ref] $dec)</b>
True
<i>PS C:\></i> $dec
573.03333333333333333333333

或者直接添加d后缀
PS C:\> Invoke-Expression ($s + 'd')
573.0333333333333333333333333

根据XLII皇帝的评论, [decimal]"5.7303333333e+02"实际上是不起作用的,因为它会通过双精度转换为十进制。尝试添加更多位数,你会立即意识到输出不再正确。
PS C:\> Trace-Command TypeConversion { [decimal]'5.7303333333e+02' } -PSHost
DEBUG: TypeConversion Information: 0 : Converting to decimal.
DEBUG: TypeConversion Information: 0 : Exception converting to decimal: "Input string was not in a correct format.". Converting to decimal passing through double.
DEBUG: TypeConversion Information: 0 : Numeric Conversion through System.Double.
573.03333333
PS C:\> [decimal]'5.7303333333e+02'
573.03333333
PS C:\> [decimal]'5.730333333333333333333333333e+02' # doesn't work
573.033333333333
PS C:\> 5.730333333333333333333333333e+02d           # correct value
573.0333333333333333333333333

正如您所看到的,如果我们使用 d 后缀 表示十进制数,我们将得到正确的高精度值。因此,一个简单的技巧就是产生一个新的 shell 来规范化该值,尽管显然会很慢,或者使用 Invoke-Expression

PS C:\> $d = '5.730333333333333333333333333e+02'
PS C:\> [decimal]$(powershell -com ($d + 'd'))
573.0333333333333333333333333
PS C:\> Invoke-Expression ($d + 'd'))
573.0333333333333333333333333

为什么 TryParse 不起作用?原因是因为Decimal.ParseDecimal.TryParse使用的默认样式是这样的

[ws][sign][digits,]digits[.fractional-digits][ws]

不允许指数。如果你阅读Parse的文档,你会看到完整的数字格式是

[ws][$][sign][digits,]digits[.fractional-digits][e[sign]digits][ws]

其中 [e]

  • 'e' 或 'E' 字符,表示该值以指数表示法表示。如果样式包括 NumberStyles.AllowExponent 标志,参数 s 可以表示指数表示法中的数字。

这意味着你需要像上面那样使用 NumberStyles.Float(其中包括 NumberStyles.AllowExponent)来使其工作


在第一段代码中,我遇到了一个错误:[ref] cannot be applied to a variable that does not exist。修复方法是 $dec = [decimal]::Parse($s, $style) - Ste
@Ste 不是的,ParseTryParse是不同的东西。正确的修复方法是在使用之前声明变量:[decimal]$dec = 0 - phuclv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接