【问题标题】:How can I convert a string such as 5.7303333333e+02 to decimal in PowerShell?如何在 PowerShell 中将 5.7303333333e+02 等字符串转换为十进制?
【发布时间】:2013-06-06 16:06:57
【问题描述】:

我正在尝试将5.7303333333e+02 等字符串转换为decimal 类型。我试过使用[decimal]::TryParse,但返回值为false。

有没有类似于[datetime]::parseexact 的方法,或者有什么干净的方法来转换这些字符串?还是我必须解析出e+02 并单独进行数学运算?

【问题讨论】:

    标签: powershell decimal data-conversion


    【解决方案1】:

    怎么样:

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

    【讨论】:

    • +1 有效。但是我想知道在后台使用了什么强制转换机制,如果不是[decimal]::TryParse("5,7303333333e+02", [ref] $dec)。问题是不受支持的科学记数法,因为[decimal]::TryParse("5,7303333333", [ref] $dec) 确实有效...请参见此处:msdn.microsoft.com/en-us/library/9zbda557.aspx
    • 我很惊讶它有效,但 [decimal]::TryParse 没有。无论如何,看起来比使用 TryParse 要干净得多。
    • @davor:使用Trace-Command TypeConversion { [decimal]'5.7303333333e+02' } -PSHost ,可以看到PowerShell捕获了格式异常,并通过[double]解析,然后转换为[decimal]重新尝试转换。
    • 这不起作用。 [decimal]'5.730333333333333333333333333e+02' 将返回不正确的值
    【解决方案2】:

    TL;DR:

    您需要指定NumberStyles.Float

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

    或附加d 后缀

    PS C:\> Invoke-Expression ($s + 'd')
    573.0333333333333333333333333
    

    作为Emperor XLII commented above[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 suffix 表示十进制,我们将获得正确的高精度值,所以一个简单的技巧就是生成一个新的 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's documentation,您会看到完整的数字格式是

    [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 no、ParseTryParse 是不同的东西。正确的解决方法是在使用之前声明变量:[decimal]$dec = 0
    猜你喜欢
    • 1970-01-01
    • 2013-02-07
    • 2021-09-30
    • 2011-08-25
    • 2014-04-28
    • 1970-01-01
    • 2018-08-31
    • 2022-07-22
    • 1970-01-01
    相关资源
    最近更新 更多