J语言初步,绝妙的符号系统,神的计算器

简介

J语言更像是一个大型符号系统,用以解决复杂的数学运算。所以在下载J语言之后,进入jconsole,就可以凭借感觉进行数学运算了。

其中加减乘除分别是+, -, *, %。但是玩过这么多编程语言,对这些常规的运算其实已经有些倦怠了,所以直接来个鬼酷一点的,事先说明,J语言中NB.后为注释。

   1 2 3 4 5 * 2  NB. 数乘列表
2 4 6 8 10
   8 <: 7 8 9     NB. 数值和列表比较
0 1 1
   7 8 9 < 9 8 7  NB. 列表和列表比较
1 0 0
   (+/ % #) 2.5 3.1 11 2         NB. 求均值
4.65
   fact=: 1: ` (* $:@<:) @. *    NB. 此为阶乘
   fact 5         NB. 计算5的阶乘
120

前三条很容易理解,就不解释了;第五条稍微有点难,也先不解释。这里先看看求均值的代码(+/ % #),其中%是个二元运算符——除法,这个除法作用在两个符号之间,其中+/用于数列求和,#则返回数列长度,二者相除就得到均值。

这个就是J语言符号运算的魅力,而且J语言提供了Android等版本,可以在手机上使用,下载地址:Android版本IOS版本,在手机上的效果为

在这里插入图片描述

接下来,为了理解阶乘代码,先做一点最基础的J语言符号训练,主要包括三个内容,一是基础的运算符号;二是与if相关的语句;三是复合语句的概念。

算术符号和优先级

初学J语言,可以把运算符分为两类,即一元运算符和二元运算符,有的时候,同一个符号在进行一元或者二元运算的时候,会有不同的含义,例如%作为二元运算,表示除法,作为一元运算,表示求倒数

   % 5
0.2
   3 % 5
0.6

下表中列出了常见的算术符号

+-*%^%:
一元负号正号取符号倒数e指数根号
二元乘方猜猜是什么

其中-作为一元运算表示取负,而J语言中的复数用下划线表示,即_1表示 − 1 -1 1

和其他语言不同,J语言中乘法并不比加法优先,如果想更改二元运算的顺序,可以使用括号。而一般来说,一元运算比二元运算有着更高的优先级。

   2 * 3 + 4      NB. J语言中乘法并不比加法更优先
14
   (2 * 3) + 4    NB. 但括号还是优先的
10
   2 * * -3       NB. * -3-3的符号,为-1
_2                NB. 然后2乘以负一得到-2

赋值和比较

J语言中,通过=:进行变量赋值,而且作为函数式语言,=:不仅可以赋值变量,也可以赋值函数

   a =: 5   NB.5赋值给a
   a
5
   b =: -   NB. 把运算-赋值给b
   b a      NB. 相当于 - a
_5
   a b a    NB. 相当于 a - a
0
   type 'b'
┌────┐
│verb│
└────┘
   type 'a'
┌────┐
│noun│
└────┘

type可以返回符号的类别,在其他语言中,我们一般把-称作运算符,但在J语言中,则称作动词;而变量则为名词。在J语言中,还有副词、连词等。

=:用于赋值,而其他语言中常用的=在J语言中则表示相等

符号含义符号含义
=判断相等=:赋值
<小于<:小于等于
>大于>:大于等于

复合动词

通过=:可以进行赋值,而且可以赋值为名词,还可以赋值为动词,例如<:>:分别表示减1和加1,但容易记混,所以下面新建两个函数表示

   addOne =: >:
   minusOne =: <:
   addOne 10
11
   minusOne 10
9

这个本来没什么,不过在多个动词连接时却出现了问题,比如想实现类似 1 x + 1 \frac{1}{x}+1 x1+1的功能,如果x=5,那么就是下面这种

   >: % 5
1.2

那么如果想做一个复合函数,也理应是test =: >: %,但下面显然是错的

   test =: >: %
   test 5
1

错误的原因也很离谱,test 5实际上执行的是5 >: % 5,其中%被翻译为单目运算符取倒数;>:被翻译为双目运算符,用于比较,最后自然 5 > 1 5 5>\frac 1 5 5>51为真,即返回1。

换言之,:> %在未指定输入的情况下,是有歧义的。

为了避免这个尴尬的问题,通过@对动词进行复合是个好办法

   test =: >: @ %
   test 2
1.5

其中,@就起到了函数复合的作用,相当于把函数 f f f g g g,变为 f ( g ( x ) ) f(g(x)) f(g(x))

动词列表

如果想用同一个动词,处理多个不同的值,那么可以先用不同的值做一个列表。

   % 2 3 4
0.5 0.333333 0.25

但是,若想用不同的动词,处理同一个数值,那可能就不能这么直接列出来了,因为按照J的脾气,肯定先复合了再说,想做一个动词列表,那么需要用括号,然后中间用,或者`分隔,类似下面这种

   (%, ^) 5
0.2 148.413

需要注意,中间的逗号如果没有的话,那么最终的结果还是复合,只不过换了个复合的方法

   % ^ 5
0.00673795
   (% ^) 5
0.0336897

上面执行的计算是 1 e 5 \frac{1}{e^5} e51,下面执行的运算是 5 / e 5 5/e^5 5/e5,即()把其左侧的运算符理解为了双目计算,并将输入的5分成两份分别送到了表达式两端。

(,)虽然能实现列表,但是这个列表也有一个问题,即无论何时都会一起使用。正常列表,比如[1,2,3],那讲道理我把其中的2提取出来专门处理肯定也是没问题的,但函数上面的函数列表好像不太行。

为了解决这个问题,J语言提供了`…@.语句。

由于`在Markdown中是负责高亮的,所以`自己就没法高亮了……具体使用方法,直接看下面的代码

   test =: % ` ^
   (test@.0) 3
0.333333
   (test@.1) 3
20.0855

理解阶乘!!

再有了上面这些代码的积淀之后,只需在知道两件事就可以看懂阶乘的代码了,这两件事分别是J语言中的两类特殊函数。

一类是1:函数,表示常量函数,1:的返回值永远是1;相应地_3:返回值永远是-3,这样的函数共有19个,值从-99

另一类则是创建递归函数必不可少的$:,表示调用自身。

接下来就回顾一下阶乘代码

fact=: 1: ` (* $:@<:) @. *

其中*用于返回符号,当输入值x大于1时,* x=1,当输入值x=0时,* x =0

如果*x=0,那么fact就选择左边的1:函数,此函数无论输入什么,返回值都是1。

如果*x=1,那么就选择右侧的(* $:@<:),此函数最外层是(* ),将输入的值 x x x变为x * ($:@<:)$:表示调用自身,:<减一,二者结合就成了f(x-1)

至此,也就明白了阶乘是怎么来的,同时也基本上算是上了J语言的船。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微小冷

请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值