`
silentlakeside
  • 浏览: 107248 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Q for Mortals2笔记 -- 基本操作

    博客分类:
  • kdb+
阅读更多

 

函数的介绍

调用函数的时候用[]来分隔函数名和参数,在参数列表中用;分隔各参数,如f[x;y]。操作符实际上也是函数,只不过函数通常写法是函数名+参数,而操作符是介于操作数中间。

 

Verb:二元操作符,例如2+3中的+操作符,verb也可以使用通常的函数表达式,如+[2;3],甚至混合使用,如(2+)[3],(2+)3也是可以的。

 

基本操作符:内建的二元原子操作符(操作原子数据类型),包括数值计算、关系、比较操作符。

 

列表的智能处理

某些智能的原子操作函数或者操作符不仅能操作原子数据类型,当参数是列表的时候,它们能将操作应用到列表上的每一个元素上。下面列举了当其中一个或多个参数是列表时返回值列表的第i个元素的值

操作 返回值的第i个元素的值
m[L] m[L[i]]
a op L a op L[i]
L op a L[i] op a
L1 op L2 L1[i] op L2[i]

 

这个特点很重要,尤其是对于从传统的编程语言(Java/C/C++/C#等)转向KDB编程的人。例如KDB对表操作实际上是对每个列进行操作,但在q代码里很多时候(使用内建操作符、函数)看不出来,当你使用自定义函数的时候就会遇到麻烦。

 

要注意的是,如果参数都是列表,这种智能处理一般要求这些列表的长度一致。

q)1 2 3=1 2 3
111b
q)1=1 2 3
100b
q)" ">"abc"
000b
q)"  ">"abc"
'length 

操作符优先级

q没有定义任何优先级,表达式的计算顺序是从右到左。括号可以用于改变优先级。

不定义操作符优先级的原理

如果定义了操作符优先级,表达式的所有元素需要在执行前先分析一遍以找出执行顺序(效率低?),而且经常需要用括号来改变优先级。另外如果一个语言支持将二元函数当做操作符,例如f[x;y]可以写作x f y,那么还需要修改操作符优先级以支持这个特性,这不仅不切实际,还会导致更多的括号。

Match (~)

用于比较两个实体。相等的实体有相同的shape(结构?),类型,值(注意不同类型的不能相等,如42i ~ 42h返回0b),但可能占用不同的存储位置(有点类似Java两个对象是相等的--equals,但不一定是同一个对象--==)。

关系操作符

关系操作符操作的是原子类型。

等于(=)和不等于(<>)

=和~的区别:

  • =只操作原子数据类型
    q)L1:1 2 3
    q)L2:1 2 3
  • 对于数值和字符类型,=不需要相同的数据类型,symbol只能跟symbol比较
    q)42=42.0
    1b
    q)`4="4"
    'type
    q)`42=`42
    1b

<>相当于not =

q)a:42
q)b:98.6
q)a<>b
1b
q)not a=b
1b 

注意比较浮点数的时候,会有一个允许的乘法误差,例如

q)r:1%3
q)r
0.3333333
q)2=r+r+r+r+r+r
1b 

非0(not)

not只能操作数值、字符类型和时间类型,不能用于symbol。not其实就是一个判断是不是0的操作(时间类型用not操作符其实没有太大意义,2000年1月1日0时整和00:00:00.000代表是0,其他日期或者时间not返回值都是0b)

q)not 0
1b
q)not 1
0b
q)not 42
0b
q)not `0
'nyi 

排序(<,<=,>,>=)

  • 数值和字符的比较就是看它们的数值(字符的数值是ASCII码)
  • Symbol的比较是按字典顺序(我猜测是根据每个字母去比较,首字符跟首字符比较,第二个字符跟第二个字符比较,以此类推,空小于任何非空;字符间的比较应该还是按ASCII码)
    q)`a>=`b
    0b
    q)`ab>`abc
    0b
    q)`1>`2
    0b
    q)`>`0
    0b

列表的智能处理

虽然我们说关系操作符操作的是原子类型,事实上写代码的时候我们可以操作列表,这是因为这些操作符会自动处理列表。注意原子类型跟列表是拿原子类型跟列表的每个元素比较,列表跟列表比较是拿每个同位置元素去比较,最后返回的也是一个列表。如果两个都是列表但是长度不一样的话会返回`length错误

q)1 2 3=1 2 3
111b
q)1=1 2 3
100b
q)" ">"abc"
000b
q)"  ">"abc"
'length

 基本算术运算符+-*%

/用于注释所以用%表示除法。

 

除除法外(除法的返回值永远是浮点数),返回值的类型决定于操作数,精度低的类型会被提升为精度高的(二进制数据会被转换为int)。计算结果不会被自动转换,例如溢出会被忽略

q)i:2147483647i
q)i+3i
-2147483646i 

注意这些算术运算符都是二元的,-可以用于代表负数,但是它不能作为操作符把一个值转换成负数,可以用neg来转换为负数

q)a:-4
q)a
-4
q)-a
'-
q)neg a
4 

 Max(|)和Min(&)

这两个操作符是原子数据操作符和二元的,返回值类型是操作数中精度较高的类型。数值类型和字符类型可以一起比较,symbol类型无法参与这种比较。|也可以写作or,&可写作and

 

要注意的是这两个操作符跟Java中的含义不一样,Java里它们是逻辑操作符,返回值是true或者false;q里返回值是两个操作数的最大值或者最小值,不一定是boolean值,虽然它们经常用于boolean判断。

 

q)0b|1b
1b
q)42|42.1
42.1
q)"a"|"z"
"z"
q)`a|`z
'type

 指数操作符:sqrt、exp、log、xexp、xlog

这些操作的返回值都是浮点数,如果遇到不合法的情况返回的是浮点数空值(0n,不是0,浮点数0是0f),例如对负数开方等。

  • sqrt:开平方
  • exp:自然对数的底数(e)的幂
  • log:自然对数
  • xexp:幂,二元操作,表示一个数的几次方
  • xlog:对数,二元操作

其他基本操作符:mod、signum、reciprocal、floor、ceiling、abs

  • mod:取模
  • signum:正负号函数,返回1i(正数)、-1i(负数)和0i(0)
  • floor:向下取整,只能用于int、long和浮点数,不能用于boolean、byte、short
  • ceil:向上取整,只能用于int、long、boolean、byte和浮点数,不能用于short
  • abs:取绝对值

时间数据操作

时间数据的内部形式

时间数据实际上是以有符号的浮点数存储的

  • 对于date和datetime来说,0.0表示2000年1月1日0时整。整数部分表示日期相对于2000年1月1日的天数偏差,小数部分表示相对于1整天的比例,例如中午12点整是0.5
  • 对于time来说,它是从一天0时整开始的毫秒数

基本操作

date/datetime之间的操作基于它们所代表的浮点数,而time之间的比较基于它们代表的毫秒数。

 

date和time可以相加得到一个datetime

q)2007.07.04+12:45:59.876
2007.07.04D12:45:59.876000000 

当时间数据与数值类型比较时,取其代表的浮点数来进行计算。

 

当时间数据与数值类型进行加减操作时,相当于浮点数计算然后将结果转换为时间类型,例如date/datetime类型-2相当于减去两天。注意时间超出24小时的时候结果是这样的

q)23:59:59.999+2
24:00:00.001 

 

当时间数据之间进行减法操作时,取其代表的浮点数来计算,结果可以认为是天数或者毫秒数。

 

无穷数和空的操作

 产生无穷数

非零数除以0即可得到float类型的无穷数(0w或者-0w)。int的无穷数不能通过除0得到,因为除法的返回值只能是浮点数。

产生NaN

0除以0即可得到NaN(浮点数的空:0n)

无穷数和空的基本算术操作

如果表达式的一个成员是无穷数或者空,则结果就是无穷数或者空,其中NaN>>空>>无穷数。注意正负无穷数所带的正负号对结果仍然有影响。例外的是正无穷整数和负无穷整数相加的结果是0的整数。

类型提升

在混合类型的表达式中,空值的类型提升跟有穷数的规则一样。

相等性

无穷数不等于大多数数值,包括空。所有的空都相等,因为它们的区别只是类型。整数类型的无穷数其实是用该类型的最大值存储的,因此它们等于该类型的最大数,如

q)32767=0Wh
1b
q)-32767=-0Wh
1b

Match

Match跟相等不一样,因为match会比较类型。拿整数类型的无穷数跟同类型的最大值比较,结果也是1b(注意同类型)

q)-32767h~-0Wh
1b
q)-32767~0Wh
0b 

not

非零操作对于所有的无穷数和空都是返回0b。

neg

无穷数有正负号,所以neg操作跟普通数值一样。空值没有正负号,因此返回还是自身。

比较

空值< -0wf < -0Wj < -0Wi < -0Wh < 非无穷数数值 < 0Wh < 0Wi < 0Wj < 0wf。空symbol小于任何其他symbol。

 

记住每个类型的无穷数都是该类型的最大值,所以long无穷数>int无穷数>short无穷数。

Max和Min

max和min操作依据上面的相等和比较操作结果而定。要注意的是,如果包含无穷数的表达式中出现了类型提升,那么结果可能不是无穷数。

q)0Ni&100f
0n
q)0Wi&0Wj
2147483647 

别名(alias)

别名是包含了其他变量的表达式。

别名和Double assignment

::是double assignment。它用于定义别名。别名的值不是赋值的时候确定的,而是动态的根据其对应的表达式的值变化而变化。别名跟普通变量的区别就是普通变量是固定值的(赋值后不再变化,除非重新赋值),而别名的值是动态的(赋值之后随所定义的表达式的值变化而变化)。

q)a:42
q)b::a
q)c:a
q)b
42
q)c
42
q)a:98.6
q)b
98.6
q)c
42

 

别名的作用类似于一个函数,别名更加方便,但别名容易引起误解,函数更加明显的定义了依赖关系。

 

别名也可以引用别名从而组成一条链。但不允许封闭的依赖链。

q)a:42
q)b::a
q)c::b+1000
q)b
42
q)c
1042
q)a:98.6
q)b
98.6
q)c
1098.6
q)a::c
'loop 

别名还可以用于产生数据库的视图(注:原书上的代码用:定义这个视图,应该是错误的,应该用::--也许是因为版本变更所致,也许是原书错误--,如下所示)

q)t:([]c1:`a`b`c`a;c2:20 15 10 20;c3:99.5 99.45 99.42 99.4)
q)va:select sym:c1,px:c3 from t where c1=`a
q)va
sym px
--------
a   99.5
a   99.4
q)va2::select sym:c1,px:c3 from t where c1=`a
q)va2
sym px
--------
a   99.5
a   99.4
q)update c3:100.0 from `t where c1=`a
`t
q)t
c1 c2 c3
-----------
a  20 100
b  15 99.45
c  10 99.42
a  20 100
q)va
sym px
--------
a   99.5
a   99.4
q)va2
sym px
-------
a   100
a   100

注意,::还有设定为全局范围的作用,请参考global amend

依赖关系

.z.b可以返回依赖列表。原书所说视图的依赖关系不显示在这个列表里应该也是错误的,怀疑是作者并没有用::实际产生一个视图导致。

q).z.b
a| b
b| c
t| va2 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics