about_Arithmetic_Operators

简短说明

介绍在 PowerShell 中执行算术的运算符。

长说明

算术运算符计算数值。 可以使用一个或多个算术运算符来添加、减去、乘法和除法值,并计算除法运算) 的余数 (模数。

此外,加法运算符 (+) 和乘法运算符 (*) 也对字符串、数组和哈希表进行操作。 加法运算符连接输入。 乘法运算符返回输入的多个副本。 甚至可以在算术语句中混合对象类型。 用于计算 语句的方法由表达式中最左侧对象的类型确定。

从 PowerShell 2.0 开始,所有算术运算符都处理 64 位数字。

从 PowerShell 3.0 开始, -shr 将添加 (向右移) 和 -shl (左移) ,以支持 PowerShell 中的按位算术。

PowerShell 支持以下算术运算符:

运算符 说明 示例
+ 添加整数;串连 6 + 2
字符串、数组和哈希表。 "file" + "name"
@(1, "one") + @(2.0, "two")
@{"one" = 1} + @{"two" = 2}
+ 从对象中生成数字 + 123
- 两个值相减 6 - 2
value
- 计算相反的数字 - -6
(Get-Date).AddDays(-1)
* 乘以数字或复制字符串 6 * 2
和 数组指定数字 @("!") * 4
时间。 "!" * 3
/ 两个值相除。 6 / 2
% 模数 - 返回 的余数 7 % 2
除法运算。
-乐队 位与 5 -band 3
-bnot 按位“非” -bnot 5
-博尔 按位“或” 5 -bor 0x03
-bxor 按位“异或” 5 -bxor 3
-shl 向左移动位 102 -shl 2
-Shr 将位向右移动 102 -shr 2

按位运算符仅适用于整数类型。

运算符优先顺序

PowerShell 按以下顺序处理算术运算符:

优先顺序 操作员 说明
1 () 括号
2 - 对于负数或一元运算符
3 *, /, % 用于乘法和除法
4 +, - 用于加法和减法
5 -band, -bnot 对于按位运算
5 -bor, -bxor 对于按位运算
5 -shr, -shl 对于按位运算

PowerShell 根据优先规则从左到右处理表达式。 以下示例显示了优先规则的效果:

表达式 结果
3+6/3*4 11
3+6/(3*4) 3.5
(3+6)/3*4 12

PowerShell 计算表达式的顺序可能与你使用过的其他编程和脚本语言不同。 以下示例演示了一个复杂的赋值语句。

$a = 0
$b = @(1,2)
$c = @(-1,-2)

$b[$a] = $c[$a++]

在此示例中,表达式 $a++ 在 之前 $b[$a]计算。 在 $a++ 语句$c[$a++]中使用 后,求值$a会更改 ;但在 中$b[$a]使用它之前, 中的 变量$a等于 1,而不是 0;因此,语句将值赋给 $b[1],而不是 $b[0]$b[$a]

上述代码等效于:

$a = 0
$b = @(1,2)
$c = @(-1,-2)

$tmp = $c[$a]
$a = $a + 1
$b[$a] = $tmp

除法和舍入

当除法运算的商为整数时,PowerShell 会将值舍入为最接近的整数。 当值为 .5时,它会舍入到最接近的偶数整数。

以下示例演示舍入到最接近的偶数整数的效果。

表达式 结果
[int]( 5 / 2 ) 2
[int]( 7 / 2 ) 4

请注意 5/2 = 2.5 如何舍入到 2。 但是, 7/2 = 3.5 将舍入到 4

可以使用 [Math] 类获取不同的舍入行为。

表达式 结果
[int][Math]::Round(5 / 2,[MidpointRounding]::AwayFromZero) 3
[int][Math]::Ceiling(5 / 2) 3
[int][Math]::Floor(5 / 2) 2

有关详细信息,请参阅 Math.Round 方法。

添加和乘法非数值类型

可以添加数字、字符串、数组和哈希表。 还可以将数字、字符串和数组相乘。 但是,不能将哈希表相乘。

添加字符串、数组或哈希表时,元素会连接在一起。 连接集合(如数组或哈希表)时,将创建一个新对象,其中包含这两个集合中的 对象。 如果尝试连接具有相同键的哈希表,操作将失败。

例如,以下命令创建两个数组,然后添加它们:

$a = 1,2,3
$b = "A","B","C"
$a + $b
1
2
3
A
B
C

还可以对不同类型的对象执行算术运算。 PowerShell 执行的操作由操作中最左侧对象的 Microsoft .NET 类型决定。 PowerShell 尝试将操作中的所有对象转换为第一个对象的 .NET 类型。 如果成功转换对象,它将执行适用于第一个对象的 .NET 类型的操作。 如果无法转换任何对象,则操作将失败。

以下示例演示了加法运算符和乘法运算符的使用:包含不同对象类型的操作。 假设 $array = 1,2,3$red = [ConsoleColor]::Red$blue = [ConsoleColor]::Blue

表达式 结果
"file" + 16 file16
$array + 16 1,2,3,16
$array + "file" 1,2,3,file
$array * 2 1,2,3,1,2,3
"file" * 3 filefilefile
$blue + 3 Red
$red - 3 Blue
$blue - $red -3
+ '123' 123

由于用于计算语句的方法由最左侧的对象决定,因此 PowerShell 中的加法和乘法并非严格可交换。 例如, (a + b) 并不总是等于 (b + a),也不 (ab) 总是等于 (ba)

以下示例演示了此原则:

表达式 结果
"file" + 16 file16
16 + "file" Cannot convert value "file" to type "System.Int32".
Error: "Input string was not in a correct format."
At line:1 char:1
+ 16 + "file"

哈希表的情况略有不同。 可以将哈希表添加到另一个哈希表,只要添加的哈希表没有重复键。

以下示例演示如何相互添加哈希表。

$hash1 = @{a=1; b=2; c=3}
$hash2 = @{c1="Server01"; c2="Server02"}
$hash1 + $hash2
Name                           Value
----                           -----
c2                             Server02
a                              1
b                              2
c1                             Server01
c                              3

以下示例引发错误,因为其中一个键在两个哈希表中都重复。

$hash1 = @{a=1; b=2; c=3}
$hash2 = @{c1="Server01"; c="Server02"}
$hash1 + $hash2
Item has already been added. Key in dictionary: 'c'  Key being added: 'c'
At line:3 char:1
+ $hash1 + $hash2
+ ~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException

此外,还可以向数组添加哈希表;并且,整个哈希表将成为数组中的一个项。

$array1 = @(0, "Hello World", [datetime]::Now)
$hash1 = @{a=1; b=2}
$array2 = $array1 + $hash1
$array2
0
Hello World

Monday, June 12, 2017 3:05:46 PM

Key   : a
Value : 1
Name  : a

Key   : b
Value : 2
Name  : b

但是,不能将任何其他类型添加到哈希表。

$hash1 + 2
A hash table can only be added to another hash table.
At line:3 char:1
+ $hash1 + 2

尽管加法运算符非常有用,但使用赋值运算符将元素添加到哈希表和数组。 有关详细信息,请参阅 about_assignment_operators。 以下示例使用 += 赋值运算符将项添加到数组:

$array = @()
(0..9).foreach{ $array += $_ }
$array
0
1
2

类型转换以适应结果

PowerShell 会自动选择最能表达结果且不会丢失精度的 .NET 数值类型。 例如:

2 + 3.1
(2).GetType().FullName
(2 + 3.1).GetType().FullName
5.1
System.Int32
System.Double

如果操作的结果对于 类型来说太大,则结果的类型将扩大以适应结果,如以下示例所示:

(512MB).GetType().FullName
(512MB * 512MB).GetType().FullName
System.Int32
System.Double

结果的类型不一定与操作数之一相同。 在以下示例中,负值不能强制转换为无符号整数,并且无符号整数太大,无法强制转换为 Int32

([int32]::minvalue + [uint32]::maxvalue).gettype().fullname
System.Int64

在此示例中, Int64 可以同时容纳这两种类型。

类型 System.Decimal 为异常。 如果任一操作数具有 Decimal 类型,则结果将为 Decimal 类型。 如果结果对于 Decimal 类型来说太大,则不会转换为 Double。 相反,会产生错误。

表达式 结果
[Decimal]::maxvalue 79228162514264337593543950335
[Decimal]::maxvalue + 1 Value was either too large or too small for a
Decimal.

算术运算符和变量

还可以将算术运算符与变量一起使用。 运算符作用于变量的值。 以下示例演示如何将算术运算符与变量结合使用:

表达式 结果
$intA = 6
$intB = 4
$intA + $intB
10
$a = "Power"
$b = "Shell"
$a + $b
PowerShell

算术运算符和命令

通常,在包含数字、字符串和数组的表达式中使用算术运算符。 但是,还可以将算术运算符与命令返回的对象和这些对象的属性一起使用。

以下示例演示如何通过 PowerShell 命令在表达式中使用算术运算符:

(get-date) + (new-timespan -day 1)

括号运算符强制按此顺序计算 Get-Date cmdlet 和 cmdlet 表达式的计算 New-TimeSpan -Day 1 。 然后使用 运算符添加 + 这两个结果。

Get-Process | Where-Object { ($_.ws * 2) -gt 50mb }
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
   1896      39    50968      30620   264 1,572.55   1104 explorer
  12802      78   188468      81032   753 3,676.39   5676 OUTLOOK
    660       9    36168      26956   143    12.20    988 PowerShell
    561      14     6592      28144   110 1,010.09    496 services
   3476      80    34664      26092   234 ...45.69    876 svchost
    967      30    58804      59496   416   930.97   2508 WINWORD

在上述表达式中, ($_.ws) 的每个进程工作空间乘以 2;并且,结果与 进行比较 50mb ,以查看它是否大于该空间。

位运算符

PowerShell 支持标准的按位运算符,包括按位 AND (-bAnd) 、非独占和独占位 OR 运算符 (-bOr-bXor) ,以及按位-NOT (-bNot) 。

从 PowerShell 2.0 开始,所有按位运算符都使用 64 位整数。

从 PowerShell 3.0 开始, -shr 引入了 (右移) 和 -shl (左移) ,以支持 PowerShell 中的按位算术。

PowerShell 支持以下按位运算符。

运算符 说明 表达式 结果
-band 位与 10 -band 3 2
-bor 按位或 (非独占) 10 -bor 3 11
-bxor 按位或 (独占) 10 -bxor 3 9
-bnot 按位“非” -bNot 10 -11
-shl Shift-left 102 -shl 2 408
-shr Shift-right 102 -shr 1 51

按位运算符作用于值的二进制格式。 例如,数字 10 的位结构基于 1 字节) 00001010 (,数字 3 的位结构00000011。 使用按位运算符比较 10 到 3 时,将比较每个字节中的单个位。

在按位 AND 运算中,仅当两个输入位均为 1 时,生成的位才设置为 1。

1010      (10)
0011      ( 3)
--------------  bAND
0010      ( 2)

在按位 OR (包含) 运算中,当其中一个或两个输入位均为 1 时,生成的位设置为 1。 仅当两个输入位都设置为 0 时,生成的位才会设置为 0。

1010      (10)
0011      ( 3)
--------------  bOR (inclusive)
1011      (11)

在按位 OR (异) 运算中,仅当一个输入位为 1 时,生成的位才设置为 1。

1010      (10)
0011      ( 3)
--------------  bXOR (exclusive)
1001      ( 9)

按位 NOT 运算符是生成值的二进制补数的一元运算符。 位 1 设置为 0,位 0 设置为 1。

例如,0 的二进制补数为 -1,最大无符号整数 (0xffffffff) ,-1 的二进制补数为 0。

-bNot 10
-11
0000 0000 0000 1010  (10)
------------------------- bNOT
1111 1111 1111 0101  (-11, xfffffff5)

在按位左移运算中,所有位都向左移动“n”位置,其中“n”是右操作数的值。 零插入到 1 的位置。

当左操作数是整数 (32 位) 值时,右操作数的下 5 位确定左操作数的移位数。

当左操作数是长 (64 位) 值时,右操作数的下 6 位确定左操作数的移位数。

表达式 结果 二进制结果
21 -shl 0 21 0001 0101
21 -shl 1 42 0010 1010
21 -shl 2 84 0101 0100

在按位右移运算中,所有位都向右移动“n”位置,其中“n”由右操作数指定。 将正值或无符号值向右移动时,右移运算符 (-shr) 在最左侧的位置插入零。

当左操作数是整数 (32 位) 值时,右操作数的下 5 位确定左操作数的移位数。

当左操作数是长 (64 位) 值时,右操作数的下 6 位确定左操作数的移位数。

表达式 结果 二进制 Hex
21 -shr 0 21 0001 0101 0x15
21 -shr 1 10 0000 1010 0x0A
21 -shr 2 5 0000 0101 0x05
21 -shr 31 0 0000 0000 0x00
21 -shr 32 21 0001 0101 0x15
21 -shr 64 21 0001 0101 0x15
21 -shr 65 10 0000 1010 0x0A
21 -shr 66 5 0000 0101 0x05
[int]::MaxValue -shr 1 1073741823 0x3FFFFFFF
[int]::MinValue -shr 1 -1073741824 0xC0000000
-1 -shr 1 -1 0xFFFFFFFF

另请参阅