Q_06_03 表达式

表达式 

分组

给定任何表达式,括在圆括号中的相同表达式是相同类型的表达式。 例如, (7)是一个Int表达式, ([1;2;3])Int类型数组的表达式, ((1,2))是类型为(Int, Int)的表达式。

类型模型中描述的简单值和单元素元组之间的等价性消除了(6)作为一个组和(6)作为单元素元组之间的歧义。

符号

绑定或分配给类型'T值的符号的名称是'T类型的表达式。 例如,如果符号count绑定到整数值5 ,则count是一个整数表达式。

数字表达式

数字表达式是IntDouble类型的表达式。 也就是说,它们可以是整数或浮点数。

Q#中的Int文字与C#中的整数文字相同,不同之处在于不需要(或允许)结尾的“l”或“L”。 前缀“0x”支持十六进制整数。

Q#中的双字面值与C#中的双字面值相同,不同之处在于不需要(或允许)结尾的“d”或“D”。

给定任何元素类型的数组表达式,可以使用Length内置函数形成一个Int表达式,并将数组表达式放在圆括号() 例如,如果将a绑定到数组,则Length(a)是一个整数表达式。 如果b是整数数组Int[][] ,那么Length(b)Length(b)中子数组的数量, Length(b[1])是第二个子数组中的整数数在b

给定两个数字表达式,二元运算符+-*/可用于形成新的数字表达式。 如果两个构成表达式都是Double ,则新表达式的类型将为Double如果两个构成表达式都是整数,则它们将是一个Int表达式。

给定两个整数表达式,可以使用% (模数), ^ (power), &&& (按位AND), ||| (按位OR), ^^^ (按位XOR), <<< (算术左移)或>>> (算术右移)操作。 要么进行换档操作的第二个参数必须大于或等于零。 转移负数的行为是未定义的。

整数除法和整数模数遵循与C#一样的负数相同的行为。 也就是说, a % b将始终与b * (a / b) + a % b具有相同的符号,并且b * (a / b) + a % b将始终等于a 例如:

ABA / BA % B
2 2 1
-2 -2 1
-5 2 -2 -1
-5 -2 2 -1

给定任何数字表达式,可以使用-一元运算符形成新的表达式。 新表达式将与组成表达式的类型相同。

给定任何整数表达式,可以使用~~~ (按位互补)一元运算符形成新的整数表达式。

Qubit表达式

唯一的量子位表达式是与量子位数组或量子位数组元素绑定的符号。 没有量子比特文字。

泡利表达式

Pauli四, PauliXPauliYPauliZ都是有效的Pauli表达。

除此之外,唯一的Pauli表达式是与Pauli数组或Pauli数组的数组元素绑定的符号。

结果表达式

两个ResultOneZero是有效的Result表达式。

除此之外,唯一的Result表达式是绑定到Result数组或Result数组的数组元素的符号。 尤其要注意的是, One与整数1不一样,并且它们之间没有直接转换。 Zero0也是如此。

范围表达式

给定任意三个Int表达式startstepstopstart .. step .. stop是一个范围表达式,其第一个元素是start ,第二个元素是start+step ,第三个元素是start+step+step等,直到stop已通过。 例如,如果step为正并且stop < start ,则范围可以是空的。 如果startstop之间的差值是step的整数倍,范围的最后一个元素将stop ; 也就是说,范围在两端都包含在内。

给定任意两个Int表达式startstopstart .. stop是一个等于start .. 1 .. stop的范围表达式start .. 1 .. stop 请注意,即使stop小于start ,隐含step为+1, 在这种情况下,范围是空的。

一些示例范围是:

  • 1..3是范围1,2,3。
  • 2..2..5是范围2,4。
  • 2..2..6是范围2,4,6。
  • 6..-2..2是范围6..-2..2
  • 2..1是空的范围。
  • 2..6..7是范围2。
  • 2..2..1是空的范围。
  • 1..-1..2是空的范围。

可调用的表达式

可调用文字是在编译范围中定义的操作或函数的名称。 例如, X是引用标准库X操作的操作文字,而Message是引用标准库Message函数的函数文字。

如果操作支持Adjoint函子,则(Adjoint op)是一个运算表达式。 同样,如果操作支持Controlled仿函数,则(Controlled op)是操作表达式。 这些表达式的类型在上面的Functors中指定。

可调用的调用表达式

给定可调用(操作或函数)表达式和可调用签名的输入类型的元组表达式,可以通过将元组表达式附加到可调用表达式来形成调用表达式。 调用表达式的类型是可调用签名的输出类型。

例如,如果Op是具有签名((Int, Qubit) => Double) Op(3, qubit1) ,则Op(3, qubit1)Double类型的表达式。 同样,如果Sin是具有签名的函数(Double -> Double) ,则Sin(0.1)Double类型的表达式。

调用可调用值表达式的结果需要在可调用表达式附近添加一对额外的括号。 因此,为了从前一段调用Op的伴随,正确的语法是:

Q#
 (Adjoint(Op))(3, qubit1) 

部分应用

给定可调用的表达式,可以通过向可调用对象提供参数的子集来创建新的可调用对象。 这被称为部分应用程序

在Q#中,部分应用的可调用是通过编写一个普通的调用表达式来表达的,但对未指定的参数使用下划线_ 结果可调用的结果类型与基本可调用结果类型相同,并且操作的变量也相同。 部分应用程序的输入类型只是删除了指定参数的原始类型。

如果在创建部分应用程序时将可变变量作为指定参数传递,则会使用该变量的当前值。 之后更改变量的值不会影响部分应用程序。

例如,如果Op有类型((Int, ((Qubit,Qubit), Double)) => ():Adjoint)

  • Op(5,(_,_))有类型(((Qubit,Qubit), Double) => ():Adjoint)Op(5,_)
  • Op(_,(_,1.0))有类型((Int, (Qubit,Qubit)) => ():Adjoint)
  • Op(_,((q1,q2),_))具有类型((Int,Double) => ():Adjoint) 请注意,我们在这里应用了单例元组等价。

递归

Q#可调参数允许直接或间接递归。 也就是说,一个操作或函数可能会调用它自己,或者它可能会调用另一个直接或间接调用可调用操作的可调用对象。

然而,有关使用递归的两个重要评论:

  • 在操作中使用递归可能会干扰某些优化。 这可能会对算法的执行时间产生重大影响。 如果阻止优化,编译器应该生成警告。
  • 在实际量子器件上执行时,堆栈空间可能会受到限制,因此深度递归可能会导致运行时错误。 特别是,Q#编译器和运行时不会识别和优化尾递归。

元组表达式

元组文字是一系列适当类型的元素表达式,用逗号分隔,并用()括起来。 例如, (1, One)是一个(Int, Result)表达式。

除文字外,唯一的元组表达式是绑定到元组值的符号,元组数组的元素元素和返回元组的可调用调用。

用户定义的类型表达式

用户定义类型的文字由类型名称组成,后跟类型的基本元组类型的元组文字。 例如,如果IntPair是基于(Int, Int)的用户定义类型,那么IntPair(2,3)将是该类型的有效文字。

除文字外,用户定义类型的唯一表达式是绑定到该类型值的符号,该类型数组的数组元素以及返回该类型的可调用调用。

数组表达式

数组文字是一个或多个元素表达式的序列,用[]分隔,用分号分隔。 所有元素必须与相同类型兼容。 如果公共元素类型是操作类型或函数类型,则所有元素都必须具有相同的签名,并且在操作的情况下具有相同的受支持的函子。

空阵列文字, [] ,是不允许的。 相反,使用new ★[0] ,其中作为适当类型的占位符,允许创建所需的长度为零的数组。

给定两个相同类型的数组,可以使用二元+运算符来形成一个新数组,即两个数组的连接。 例如, [1;2;3] + [4;5;6][1;2;3;4;5;6]

数组创建

给定一个类型和一个Int表达式, new运算符可用于分配给定大小的新数组。 例如, new Int[i+1]将分配一个带有i+1元素的新Int数组。

新数组的元素被初始化为一个依赖于类型的默认值。 在大多数情况下,这是零的一些变化。

对于对实体的引用的量子比特和可定标,没有合理的默认值。 因此,对于这些类型,缺省值是一个无效的引用,不会导致运行时错误而无法使用。 这与C#或Java等语言中的空引用类似。 包含量子位或可调参数的数组必须使用set语句填充,然后才能安全使用它们的元素。 数组元素只能在数组声明为可变时设置,例如mutable array = new Int[5] 作为参数传递的数组是不可变的。

每种类型的默认值是:

类型默认
Int0
Double0.0
Boolfalse
String""
Qubit 无效的量子比特
PauliPauliI
ResultZero
Range空的范围, 1..1..0
Callable 无效的可调用
Array['T]'T[0]

元组类型是逐元素初始化的。

数组的创建主要是使用初始化可变数组,在[ mutable ] microsoft.quantum.qsharp-ref.type-model.statements#mutable-symbols)语句的右侧。

阵列切片

给定一个数组表达式和一个Range表达式,一个新的表达式可以使用[]数组slice操作符来形成。 新的表达式将与数组的类型相同,并且将包含由Range的元素索引的数组项,按照由Range定义的顺序。 例如,如果a绑定到一个Double s数组,则a[3..-1..0]是一个Double[]表达式,它包含a的前四个元素,但是以相反的顺序出现在a

如果Range为空,则结果数组切片将为零长度。

如果数组表达式不是一个简单的标识符,则它必须包含在括号中以便分片。 例如,如果ab都是Int数组,则来自连接的切片将表示为:

Q#
 (a+b)[1..2..7] 

Q#中的所有数组都是从零开始的。 也就是说,数组a的第一个元素始终a[0]

数组元素表达式

给定一个数组表达式和一个Int表达式,可以使用[]数组元素运算符形成一个新表达式。 新的表达式将与数组的元素类型相同。 例如,如果a绑定到一个Double s数组,则a[4]是一个Double表达式。

如果数组表达式不是一个简单的标识符,则它必须用圆括号括起来以便选择一个元素。 例如,如果ab都是Int数组,则来自并置的元素将表示为:

Q#
 (a+b)[13] 

Q#中的所有数组都是从零开始的。 也就是说,数组a的第一个元素始终a[0]

布尔表达式

两个Bool文字值是truefalse

鉴于任何两个表达式与相同的基元类型兼容, ==!=二元运算符可用于构造一个Bool表达式。 如果两个表达式(不相等),表达式将为真。 对于大小和平等比较,用户定义类型的值在比较之前转换为其基本类型。

Qubit值的平等比较是身份平等; 也就是说,两个表达式是否确定相同的量子位。 两个量子的状态不会被比较,比较,访问,测量或修改。

由于四舍五入效应, Double值的平等比较可能会产生误导。 例如, 49.0 * (1.0/49.0) != 1.0

给定任意两个数字表达式,二元运算符><>=<=可用于构造一个新的布尔表达式,如果第一个表达式分别大于,小于,大于或等于或小于或等于第二个表达式。

给定任何两个布尔表达式, &&|| 二元运算符可以用来构造一个新的布尔表达式,如果两个表达式中的任何一个或两个都为真,则该布尔表达式为真。

给定任何布尔表达式, ! 一元运算符可用于构造一个新的布尔表达式,如果构成表达式为假,则为true。

运算符优先级

^以外,所有二元运算符都是右关联的。

用于数组切片和索引的括号[]绑定在任何运算符之前。 操作和函数调用的括号也绑定在任何操作符之前,但在数组索引之后绑定。

运营商按照从高到低的顺序排列:

操作者元数描述操作数类型
-~~~一元数字负数,逐位补码,逻辑否定(NOT) IntDouble-Int~~~Bool!
^二进制整数功率Int
/*%二进制分,乘,整数模 IntDouble/*Int%
+-二进制加法或字符串和数组连接,减法 IntDouble ,额外String或任何数组类型
<<<>>>二进制左移,右移Int
<<=>>=二进制小于,小于或等于,大于,大于或等于比较 IntDouble
==!=二进制相等,不等于比较任何原始类型
&&&二进制按位与Int
^^^二进制按位XORInt
|||二进制按位或Int
&&二进制逻辑ANDBool
||二进制逻辑或Bool

字符串插值

Q#允许在fail语句和Log标准函数中使用字符串。 用于字符串插值的Q#语法是C#7.0语法的子集; Q#不支持逐字(多行)插值字符串。 请参阅C#语法的插值字符串

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值