如何从Powershell中的字符串转换为UInt64?字符串到数字的转换

时间:2016-12-11 16:47:39

标签: powershell type-conversion powershell-v5.0

考虑以下Powershell片段:

[Uint64] $Memory = 1GB
[string] $MemoryFromString = "1GB"
[Uint64] $ConvertedMemory = [Convert]::ToUInt64($MemoryFromString)

第3行失败了:

Exception calling "ToUInt64" with "1" argument(s): "Input string was not in a correct format."
At line:1 char:1
+ [Uint64]$ConvertedMemory = [Convert]::ToUInt64($MemoryFromString)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : FormatException

如果我查看$Memory的内容:

PS C:\> $Memory
1073741824

工作正常。

那么,如何在Powershell中将值“1GB”从字符串转换为UInt64?

2 个答案:

答案 0 :(得分:6)

您的问题是ToUint64无法理解Powershell语法。你可以这样做:

($MemoryFromString / 1GB) * 1GB

由于$MemoryFromString将在分割之前转换为其数值。

这是有效的,因为在分割时,Powershell尝试使用其规则将字符串转换为数字,而不是将{。}规则转换为ToUInt64。作为转化的一部分,如果找到GB后缀并应用规则将"1GB"字符串展开为1073741824

编辑:或者正如PetSerAl指出的那样,你可以这样做:

($MemoryFromString / 1)

答案 1 :(得分:3)

补充 Sean's helpful answer

只有结果变量([uint64] $ConvertedMemory = ...)的类型约束才能确保($MemoryFromString / 1)转换为[uint64][System.UInt64])。

表达式$MemoryFromString / 1的结果实际上是[int][System.Int32])类型的结果:

> ('1gb' / 1).GetType().FullName
System.Int32

因此,为了确保表达式本身返回[uint64]个实例,您必须使用强制转换

> ([uint64] ('1gb' / 1)).GetType().FullName
System.Int64

请注意计算所需的(...),因为[uint64]仅适用于'1gb'(因此会失败)。
或者,('1gb' / [uint64] 1)也可以。

注意:

  • '1gb' - 0也会奏效,
  • 但是 不是 '1gb' * 1'(实际上是无操作)或'1gb' + 0(导致字符串'1gb0',因为运营商*+带有字符串 -typed LHS执行字符串操作(分别是复制和连接)。

可选背景信息:

当PowerShell执行隐式号码转换时,包括执行混合数值类型计算和解析源代码中的数字文字时,可以方便地自动选择数字类型为&#34 ;大"足以保存结果

隐式字符串到数字转换中,PowerShell可以方便地识别源代码中文字支持的格式相同的格式:

  • 类型说明符后缀L [long][System.Int64])和D [decimal]({1}} [System.Decimal]);例如,'1L' - 0产生[long] 请注意, C#使用M代替D,而是使用D来指定[System.Double];此外,C#还支持几个额外的后缀。

  • 浮点表示,例如1.23;请注意, PowerShell只会将.识别为小数点,无论当前的文化

  • 指数表示法;例如,'1.0e3' - 1会产生999

  • 自己的二进制倍增器后缀kbmbgbtbpb(对于乘数[math]::pow(2, 10) == 1024[math]::pow(2, 20) == 1048576,...);例如,'1kb' - 1产生1023;请注意,这些后缀是特定于PowerShell的,因此.NET框架编号解析方法识别它们。

数字转换规则很复杂,但这里有一些关键点

这是基于我自己的实验。如果我错了,请告诉我 类型由其PS类型加速器表示,并映射到.NET类型,如下所示:
[int] ... [System.Int32]
[long] ... [System.Int64]
[decimal] ... [System.Decimal]
[float] ... [System.Single]
[double] ... [System.Double]
功能

  • PowerShell 从不自动选择无符号整数类型

    • 十六进制数字文字可能会出乎意料;例如,[uint32] 0xffffffff 失败,因为0xffffffff 首先 - 隐式地 - 转换为签名类型[int32] ,产生-1,作为签名的值,无法转换为 unsigned 类型[uint32]
    • 解决方法:
      • 首先L强制解释为[int64],这会产生预期的正值4294967295,在这种情况下,转化为[uint32]成功。
      • 该技术不适用于0x7fffffffffffffff[long]::maxvalue)以上的值,但是,在这种情况下,您可以使用字符串转换:[uint64] '0xffffffffffffffff'
  • PowerShell 根据需要扩展整数类型

    • 对于十进制整数文字/字符串,扩展超越整数类型到[System.Decimal],然后[Double] < / strong>,根据需要; e.g:

      • (2147483648).GetType().Name会产生Int64,因为该值为[int32]::MaxValue + 1,因此会隐式加宽为[int64]

      • (9223372036854775808).GetType().Name会产生Decimal,因为该值为[int64]::MaxValue + 1,因此会隐式加宽为[decimal]

      • (79228162514264337593543950336).GetType().Name会产生Double,因为该值为[decimal] :: MaxValue + 1 , and was therefore implicitly widened to [double]`。

    • 对于十六进制(总是整数)文字/字符串,加宽[int64]

      • (0x100000000).gettype().name会产生Int64,因为该值为[int32]::MaxValue + 1,因此会隐式加宽为[int64]

      • 0x10000000000000000[int64]::MaxValue + 1,由于十六进制而解释 因此,失败

    • 注意:以上规则适用于单个文字/字符串,但表达式中的扩展可能会立即扩展到[System.Decimal](不考虑[double]) - 见下文。

  • PowerShell看似从不自动选择小于的整数类型

    • [decimal]会产生[int]('1' - 0).GetType().FullName),即使整数System.Int32适合[int]甚至1
  • 计算结果从不使用比任何一个操作数更小的类型:

    • [int16][byte]都会产生1 + [long] 1(即使结果可能适合较小的类型)。
  • 也许出乎意料的是, PowerShell会自动选择浮点类型[long] 1 + 1,以获得大于任一操作数类型的计算结果即使结果 符合更大的整数类型,整数类型也可以

    • [long]会产生[double](a ([int]::maxvalue + 1).GetType().FullName),即使结果符合System.Double整数。
    • 但是,如果其中一个操作数是足够大的整数类型,则结果属于该类型:[double]产生[long](a ([int]::maxvalue + [long] 1).GetType().FullName)。
  • 在计算中包含至少一个浮点类型始终会产生System.Int64 ,即使与整数类型混合或使用全部 - [long]个操作数也是如此:

    • [double][float]以及1 / 1.01.0 / 1以及1 / [float] 1都会产生[float] 1 / 1
  • 源代码中
  • (未加引号)的数字文字

    • 十进制整数字面值被解释为以下类型中可以容纳该值的最小值:[float] 1 / [float] 1&gt; [double]&gt; [int]&gt; [long] (!):

      • [decimal]会产生[double](如上所述,1是自动选择的最小类型)
      • [int](高于[int] 1)会产生214748364
      • [int]::maxvalue(高于[long] 1)会产生9223372036854775808
      • [long]::maxvalue(高于[decimal] 1)会产生79228162514264337593543950336
    • 十六进制整数字面值被解释为以下类型中可以容纳该值的最小值:[decimal]::maxvalue&gt; [double] ;也就是说,与十进制文字不同,不支持大于[int]的类型; 警告具有高位设置的值导致_negative_十进制数,因为PowerShell会自动选择签名的整数类型:

      • [long]会产生[long]
      • 0x1会产生[int] 值,因为高位设置为:0x80000000,这是最小值 [int]数字,如果您考虑签名(-2147483648
      • [int](比[int]::MinValue多1位)会产生0x100000000
      • [int](比[long] 中断的<1>多一点,因为0x10000000000000000是支持的最大类型(&#34) ;数字常量无效&#34;)。

      • 要确保十六进制文字产生数字,请先使用类型后缀[long]强制解释为[long],然后(可选)强制转换为 unsigned 类型;例如L会产生[long],但请注意,此技术最多只能使用[uint32] 0x80000000L,即2147483648;如上所述,使用字符串的转换作为解决方法(例如0x7fffffffffffffff)。

    • (总是十进制 浮点指数表示法 文字始终解释为[long]::maxvalue ,无论多小:

      • [uint64] '0xffffffffffffffff'[double]都会产生1.0