フィボナッチ数だけでプログラム言語に精通したつもりになる
簡単なサンプルでプログラム言語の基本をおさえる
フィボナッチ数を求めるプログラムで各言語の基本仕様をマスターしたつもりになります。
Hello World! の次にやってみればいいと思います。
サンプルでは、
- 変数の宣言とか代入(束縛)とかスコープとか
- コマンドライン引数の取得
- 文字列から数値への変換
- 関数定義と呼び出し
- 再帰関数の利用
- 条件分岐
- 文字列(数値)の表示
- コメント文の書き方
- 大まかな実行速度
上記を一気に知ることができます。あら便利。
progopedia や似たような記事はありますが、すべてが同じアルゴリズムで、コマンドラインで動くプログラムとして完結しているものは少なかったので、まとめてみました。
(2019-06-19追記)
「様々なプログラミング言語における素数判定」が、
TD12734様によって記事になっています。
そちらもご参照ください。
(2019-06-19追記ここまで)
(2019-11-14追記)
ぼちぼち追加していたら言語数が50ぐらいになりました。
いいかげん読みにくいです。
でも、当分はそのままだと思います。
(2019-11-14追記ここまで)
(2022-4-17追記)
実行速度の再計測をしました。
Kotlin, Clojure, V, COBOL, Neko, bc, arturo, REXX, Euphoria のサンプルを追加しました。
(2022-4-17追記ここまで)
フィボナッチ数とは
めんどくさいので詳しいことはWikipediaで調べてください。
ここでは簡単に書きます。
定義は、
今回は頭の悪い再帰関数を使って定義通りに39番目のフィボナッチ数「63,245,986」を計算します。
サンプルプログラム
書き方について
各言語、もっといい書き方はあるとは思いますが、なるべく方言が出ないように書いています。
そのためにその言語の標準的な書き方になっていなくて、その言語の特徴を知るということに対しては本末転倒なことになっている場合もあります。
コマンドライン引数から計算するようになっているため、最適化されて固定値を表示するだけのプログラムにはなっていません。(と思いますがそうではないかもしれません)
サンプルの順序
大体TIOBEの2016年1月の人気順位で書いてます。
途中知らない言語を飛ばしたり、CとJavaを入れ替えちゃったりしていますが。
解説について
ものすごく個人的な偏見や誤解、思い込みに満ちた解説です。
解説中ではネイティブコードとか中間コードとかにはこだわらず、雑に
コンパイルが必要な言語→コンパイル言語とかコンパイラとか
コンパイルが不要な言語→スクリプト言語とかインタプリタとか
と適当に定義しています。
「言語とコンパイラは違うだろ。」とかつっこまれそうですが、まぁなんとなく、で。
今後の予定
ABC順のインデックス
C
とりあえずお約束ということで、C言語から行きます。
多分、世界標準です。
速いし、ライブラリも豊富だし、正直これだけ知っていれば何でもできます。
と言ってしまえば、この記事の存在が危ぶまれますが。
これぐらいのプログラムであれば、PHP や JavaScript しか触ったことのない人でもわかると思います。
ポインタを理解できるかがどうかがこの言語の鍵です。
いろんなものがCで書かれているので、自分でCを書かない人でもGCCは必須。
// フィボナッチ数 by 10.2.0
#include <stdio.h>
#include <stdlib.h>
int fib(int n)
{
if (n < 2) {
return n;
} else {
return fib(n-1) + fib(n-2);
}
}
int main(int argc, char *argv[])
{
int n;
n = atoi(argv[1]);
printf("%d", fib(n));
return 0;
}
/*
Example
compile:
gcc -O3 -o fib_c fib_c.c
run:
./fib_c.c 39
*/
<近似式でやっつけ>
計測不能なタイムで瞬殺です。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[])
{
printf("%lld", (int)(pow(((1+sqrt(5))/2),atof(argv[1]))/sqrt(5)+0.5));
return 0;
}
/*
Example
compile:
gcc -O3 -lm -o fib_binet fib_binet.c
run:
./fib_binet 92
*/
Java
これまたこの業界にいて名前を知らない人はいないと思います。
昔は遅い遅いと言われましたが、JITが効くようになってからは、C言語に迫る速度です。
この言語もライブラリが豊富で、これだけでほぼ何でもできます。
この言語で開発するための時間の殆どは、クソみたいに階層の深いライブラリのどこに何があるかを探すことに費やすことです。
書き方がちょっと冗長なのが嫌いなところです。
JITで充分速いので、GNUのJavaのコンパイラgcjはもういらない子かも…。(2017年で開発終了した?)
// フィボナッチ数 by java
public class fib_java {
public static int fib(int n) {
if (n < 2) {
return n;
} else {
return fib(n-2) + fib(n-1);
}
}
public static void main(String[] args) {
int n = Integer.parseInt(args[0]);
System.out.println(fib(n));
}
}
/*
example
compile by OpenJDK:
javac fib_java.java
run by OpenJDK:
java fib_java 39
compile by gcj:
gcj -O4 --main=fib_java -o fib_gcj fib_java.java
rub by gcj:
./fib_java 39
*/
C++
C言語にオブジェクト指向を取り込んだ魔物。
この言語のダークサイドに陥れば、クラス継承の無間地獄が味わえます。
と言われていましたが、最近はオブジェクト指向を取り入れた言語も増え、
その特徴はあまり目立たなくなっています。
さすがに速度はC同様に高速。
C同様これもLinux使う分には書かなくても必須です。
// フィボナッチ数 by C++
#include <iostream>
#include <cstdlib>
using namespace std;
int fib(int n)
{
if (n < 2) {
return n;
} else {
return fib(n - 1) + fib(n - 2);
}
}
int main(int argc, char** argv)
{
int n;
n = atoi(argv[1]);
cout << fib(n) << endl;
return 0;
}
/*
example
compile:
g++ -o fib_cpp -O3 -mtune=native fibonacci.cpp
run:
./fib_cpp 39
*/
C#
Microsoft謹製のC言語もどき。
C言語とJavaを足して割ったような仕様。
VisualBasicよりもすっきりした書き方ができ、Windows界隈では標準になりそうな勢い。
ほぼ標準です。
Unityなどでもよく使われており、これからプログラムを学ぶ人は、C#から始めてもいいかもしれません。
Monoを利用すればLinuxでもコンパイルと実行が可能。
Windowsで速度比較をやっていないけど多分高速(2022時点ではそこまで高速ではなくなりました)。
LinuxではMonoに依存するのでなんとも言えませんが、スクリプトよりは速い。
言語的には嫌いではないんですがね、Visual Studioがウン…
実はC#を作った人とTurbo Pascalを作った人は同じ。
ある意味、C#はTurbo Pascalの正統な後継だったりする。かも?
// C#でフィボナッチ
using System;
class Fibonacci
{
static long Fib(int n)
{
if (n < 2)
return n;
else
return Fib(n - 2) + Fib(n - 1);
}
static void Main(string[] args)
{
int n = int.Parse(args[0]);
Console.Write(Fib(n));
}
}
/*
example
compile:
mcs -optimize+ fib_cs.cs
run:
mono fib_cs.exe 39
*/
Python
いきなりスクリプト(インタプリタ)言語。
2022年のTIOBEインデックスでついに1位になりました。
この言語の特徴はなんと言っても、インデントでブロックが決定すること。
誰が書いても綺麗に見えるプログラムが書けます。
じんこうちのうとかきかいがくしゅう向けのライブララリが充実しており、
その筋の人たちに人気です。よーわからんけど。
最近は減りましたが、中途半端にインデントつけてくれるエディタで編集すると、一発で修復不可能な状態まで破壊されちゃいます。
実行速度は遅い。バージョンが2→3になって更に遅くなりました。
ってか、微妙に互換性がない! 勘弁してください。
pypyとかは名前がいやらしいので試していません。
なぜか海外では人気。 国内でも利用者が増えました。
opencvを使った画像解析や、
scikit-learnを使った機械学習などは超楽ちん。
昔「psp」と言ってPHPに対抗してHTMLに埋め込む形式のPythonがありましたが、想像通りHTMLのインデントと混ざり合い混沌したソースになってしまい普及しなかったのはPythonの黒歴史。
# -*- coding: utf-8 -*-
# フィボナッチ数 by Python 3.8.6
import sys
def fib(n):
if n < 2 :
return n
else:
return fib(n-2) + fib(n-1)
argv = int(sys.argv[1])
print(fib(argv))
"""
example
run:
python fibonacci.py 39
"""
< メモ化版 >
グローバルなdictionaryを使ってのメモ化版
もっとスマートなやり方がありそう。
# -*- coding: utf-8 -*-
# フィボナッチ数 by Python 3.8.10
import sys
r = {0:0,1:1,2:1}
def fib(n):
global r
try:
return r[n]
except:
r[n] = fib(n - 2) + fib(n - 1)
return r[n]
argv = int(sys.argv[1])
print(fib(argv))
"""
example
run:
python fib_memo.py 39
"""
< 一般項による近似式 >
# -*- coding: utf-8 -*-
# フィボナッチ数 by Python 3.8.10
import sys
import math
def fib(n):
return math.floor(((1 + math.sqrt(5)) / 2) ** n / math.sqrt(5) + 0.5)
argv = int(sys.argv[1])
print(fib(argv))
"""
example
run:
python fib_golden.py 39
"""
< NumPyで行列を使った漸化式 >
# -*- coding: utf-8 -*-
# フィボナッチ数 by Python 3.8.10
import sys
import numpy as np
def fib(n):
return np.linalg.matrix_power(np.array([[1, 1], [1, 0]]), n)[0][1]
argv = int(sys.argv[1])
print(fib(argv))
"""
example
run:
python fib_array.py 39
"""
php
みんな大好きphp。
適当に書いてもそこそこ動くために、糞コードが繁殖しやすい。
php-7がリリースされて、速度はほぼ2倍に。Rubyとほぼ同じ速度。
php-8でもっと速くなりました。
でもphp互換のhhvmはChromeのV8並みに速い。
hhvmはphpとの互換性はなくなりました。
速さのアドバンテージもそれほどなく、hhvm(Hack)を選択する意味はあまりありません。
HTMLに組み込める仕組みは他にもJSPやらASPやらありますが、WEBデザイナーさんと共同作業がやりやすいのは、やはりPHPだと思います。
ロジックだけのphpのファイルの場合、後ろの「?>」はつけないのが流行りらしい。(定着したっぽい?)
たしかに、余計な改行に悩まされなくて良さそう。
<?php
/**
* フィボナッチ数だよ by 8.0.3
* @param int $n
* @return int
*/
function fib($n) {
if ($n < 2) {
return $n;
} else {
return fib($n-2) + fib($n-1);
}
}
print fib($argv[1]);
/*
example
run:
php fib_php.php 39
*/
< メモ化版 >
スタティック変数を使ってメモ化してみました。
<?php
/**
* フィボナッチ数だよ
* @param int $n
* @return int
*/
function fib($n) {
static $f = [0, 1];
return $f[$n] ?? ($f[$n] = fib($n-2) + fib($n-1));
}
print fib($argv[1]);
/*
example
run:
php fib_php.php 39
*/
< 末尾再帰版 >
<?php
/**
* フィボナッチ数 末尾再帰 by 8.1.4
* @param int $n
* @param int $p1 = 1
* @param int $p2 = 0
* @return int
*/
function fib($n, $p1 = 1, $p2 = 0) {
if ($n == 0) {
return 0;
} elseif ($n == 1) {
return $p1;
} else {
return fib($n - 1, $p1 + $p2, $p1);
}
}
print fib($argv[1]);
/*
example
run:
php fib_tail.php 39
*/
< php-7.4でFFI >
php-7.4で実装されたFFI。
phpから他の言語で書かれた関数等を呼び出せます。
関数をCで組めばクッソ速い。
いや、さすがにこれはずっこくない?
// フィボナッチ数 FFI用共有オブジェクト
const int fib(int n)
{
if (n < 2) {
return n;
} else {
return fib(n - 2) + fib(n - 1);
}
}
/*
Example
compile:
gcc -O3 -fPIC -o libfib.so libfib.c
*/
<?php
/**
* フィボナッチ数だよ
* ずっこい版
*/
$ffi = FFI::cdef("
const int fib(int n);
", "./libfib.so");
print $ffi->fib(intval($argv[1]));
/*
example
run:
php fib_ffi.php 39
*/
Hack
PHPとの互換性があまりにもなくなりましたので別言語として分けました。
PHPっぽい言語という認識でいいと思います。
昔はWordpressなんかも動いていました。
htmlに埋め込む書き方もできなくなり、使いどころもなくなりました。
今この言語を選択する利用がイマイチわかりません。
/**
* フィボナッチ数だよ
* @param int $n
* @return int
*/
function fib(int $n): int {
if ($n < 2) {
return $n;
} else {
return fib($n - 2) + fib($n - 1);
}
}
<<__EntryPoint>>
function main(): void {
$n = (int) (vec(\HH\global_get('argv') as Container<_>)[1]);
print fib($n);
exit(0);
}
/*
example
run:
hhvm fib.hack 39
*/
Basic
VB.Net
Microsoft仕様のBasic。
高機能になり過ぎて、書き方がすごく冗長になってしまいました。
最近はC#に人気を奪われてつつある? しまいました。
Monoで試しました。(Mono版は最近更新されてるのかな?)
速度はMonoに依存するため、MonoのC#とほぼ同じ。昔はすっげぇ遅かったけど。
' フィボナッチ数 by Visual Basic
Module Fibonacci
Function Fib(ByVal N As Integer) As Integer
If N < 2 Then
Return N
Else
Return Fib(N - 2) + Fib(N - 1)
End If
End Function
Sub Main(ByVal CmdArgs() As String)
Dim N As Integer = Integer.Parse(CmdArgs(0))
Console.WriteLine(Fib(N))
End Sub
End Module
' example
' compile:
' vbnc /optimization+ /out:fib_vbnc.exe fib_bas.bas
' run:
' mono fib_vbnc.exe 39
FreeBasic
知名度は低いが、何気にクソ速い。
GNU コンパイラコレクションに含まれることを画策している模様。
GNU Cより速いことがあります。
' フィボナッチ数 by FreeBasic
Function Fib(N As Integer) As Integer
If N < 2 Then
Fib = N
Else
Fib = Fib(N - 2) + Fib(N - 1)
End If
End Function
Dim N As Integer = ValInt(Command(1))
Print Fib(N)
' example
' compile:
' fbc -O 3 fib_fbc.bas
' run:
' ./fib_fbc 39
日本語G-BASIC(ぴゅう太)
1982年トミーが発売した世界に誇る「ぴゅう太」
その「ぴゅう太」に搭載されたBASIC。
現在、http://nrtdrv.sakura.ne.jp/gbasic/
でWindows向けのシミュレータが公開されています。
さすがに再帰呼び出しはできませんでした。
10 シキ A=0
20 シキ B1=0
30 シキ B2=1
40 マワレ 80 I=2 カラ 10
50 A=B1+B2
60 B1=B2
70 B2=A
80 トジル
90 カケ 1, A
100 ブレイク
JavaScript
WEBには欠かせない言語となりました。
とは言うものの、他の言語では少ないprototypeの概念や、関数型言語っぽい機能もあり、非常に興味深い言語。
GoogleとMozillaで開発競争をしているため、最近のJavaScriptはクソ速い。
Google→Chrome→V8
Mozilla→FireFox→Spidermonkey
サーバサイドでV8エンジンを使用するnode.jsという実装もあります。
サーバサイドとクライアントサイドで同じ言語が使えるというのは、学習コストの低減に繋がりそうですが、どのロジックがどっちで動いているのか混乱しそうで悪い予感しかしません。
JavaScriptだとついついルーズな書き方をしてしまいがちで、
かっちり書けるJavaScript拡張のTypeScriptが流行っており、素のJavaScriptを書く人が減っているような気がします。
サンプルは、V8、node、Spidermonkey で動くように書いてみました。
なんかd8コマンドでコマンドライン引数を取得することができなかったので、固定値で妥協。
// フィボナッチ数 by JavaScript
var fib = function(n) {
if (n < 2) {
return n;
} else {
return fib(n-1) + fib(n-2);
}
}
if (typeof process === "undefined" && typeof scriptArgs !== "undefined") {
// for Spidermonkey
print(fib(scriptArgs[0]));
} else if (typeof process !== "undefined") {
// for node 15.13.0
console.log(fib(process.argv[2]));
} else {
// for d8
print(fib(39));
}
/*
example
Spidermonkey:
js fib_js.js 39
Node.js:
node fib_js.js 39
v8:
d8 fib_js.js
*/
<限界まで短く書いてみた版>
アロー演算子を使うと、なぜかFireFoxで遅くなる。バグ?
(function f(n){return n<2?n:f(n-2)+f(n-1)})(39)
(f=(n)=>{return n<2?n:f(n-2)+f(n-1)})(39)
Ruby・Crystal
Ruby
Rubyは日本製のスクリプト言語。おかげで日本での人気は高く日本語のドキュメントが多い。
とはいうものの、実務でRubyというのは意外と少ない。
言語おたくにより設計されているため、プログラマが好きそうな機能がたっぷり実装されています。
書き方には寛容なところがメリットでありデメリットでもあります。
Ruby on Rails で人気爆発しましたが、個人的にはRoRは実装が重い印象があり、あまり好きではありません。
最近は人気もちょっと落ち着いてる印象。
Ruby自体は好き。
バージョンを追うごとに速くなっています。phpと速度競争をしてる?
phpにはちょっと置いて行かれた感じ? なぜか同時期のPikeと同じぐらいの速さで動きます。
# フィボナッチ数 by Ruby-3.0.0p0
def fib(n)
if (n < 2)
return n
else
return fib(n - 2) + fib(n - 1)
end
end
puts fib(ARGV[0].to_i)
=begin
example
ruby fib_rb.rb 39
=end
Crystal
CrystalはRuby風の文法のコンパイラ言語。開発元は違います。
Rubyほど文法に寛容ではないため、Rubyでだらしない書き方をしていると怒られます。
ライブラリ経由でCの関数が呼べたりする。めっちゃ速い。
本気のJavaとほぼ同じ速度の最近ちょっと気になる言語。
Rubyのプログラムがほぼそのまま動きそうですが、=begin〜=end形式のコメントブロックでエラーが出てしまいました。
# フィボナッチ数
def fib(n)
if (n < 2)
return n
else
return fib(n - 2) + fib(n - 1)
end
end
puts fib(ARGV[0].to_i)
#
# example
# compile:
# crystal compile --release -o fib_crystal fib_rb.rb
# run:
# ./fib_crystal 39
#
Perl
Perl5
CGIで一時は世界を征服した言語。
正規表現による強力な文字列操作が特徴。
恐ろしく省略できるため、自分が書いたプログラムでもすぐにわからなくなります。
実装が古く(=安定している)、速度は遅いというか、そもそも速く動かそうと思ってません(多分)。
しかしPerl形式の正規表現は他の言語に受け継がれています。
# フィボナッチ数 by Perl
sub fib
{
my $n = shift;
if ($n < 2) {
return $n;
} else {
return fib( $n - 2 ) + fib( $n - 1 );
}
}
print fib($ARGV[0]);
=pod
example
perl fib_perl.pl 39
=cut
Raku(Perl6)
出る出ると言われてなかなか出てこない次世代型Perl。
Raku で書かれたプログラムをrakudo というコンパイラが Moar VM のバイトコードに変換します。
まだ実験段階らしく速度はシェル並に遅い。
(2022年、以前よりはだいぶ速くなりましたが、まだPerl5よりは…)
Perl5との互換性も低くなかなか使いどころがない。
# フィボナッチ数 by Perl6
sub fib ($n)
{
if ($n < 2) {
return $n;
} else {
return fib( $n - 2 ) + fib( $n - 1 );
}
}
my $ARGV = @*ARGS.shift;
print fib($ARGV);
=pod
example
perl6 fib_pl.pl6 20
=cut
<無限リスト版>
Perl6では無限リストが使えます。
なかなか面白い。
# フィボナッチ数 by Perl6
sub fib ($n)
{
return (1, 1, * + * ...*)[^$n].tail;
}
my $ARGV = @*ARGS.shift;
print fib($ARGV);
=pod
example
perl6 fib2_perl.pl6 39
=cut
Pascal
かつては「アルゴリズムを勉強するならコレ」と言われた言語。
ALGOL形式のbegin〜end形式が好きな人にはたまらない言語。
Delphiが消え、使えそうなのはFree Pascal Compilerぐらい。
Free Pascal Compiler は、古いPascalの他、DelphiモードやObjectPascalモードでのコンパイルも可能。
ただ、生成されたバイナリにランタイムがくっつくので、ファイルが大きくなりがち。
最適化もいまいち。
でも個人的には愛着のある言語です。
Component Pascal は、同じ系統ではありますが、別言語です。
uses sysutils;
function fib(n:longint): longint;
begin
if (n < 2) then
fib := n
else
fib := fib(n - 2) + fib(n - 1);
end;
var
n : integer;
begin
n := StrToInt(ParamStr(1));
writeln(fib(n));
end.
(*
example
compile(Free Pascal Compiler):
fpc -O4 -Tlinux fib_pascal.pas
*)
Swift
2016年にブレイクしそうな言語。Mac OSXのXcodeに採用されました。
iOS向けの開発やるならこれ一択です。
今からObjective Cを始める意味はほぼないです。
ちょっと関数型言語っぽい仕様なのでクセがあります。
Clangを使っているので速度もClangでコンパイルされたCとほぼ同じ。
これが出たことでObjective-Cの立場が微妙になりそう。 なくなりました。
// フィボナッチ数 by swift-5.3.3
func fib(num n: Int) -> (Int) {
if n < 2 {
return n
} else {
return fib(num: n - 2) + fib(num: n - 1)
}
}
let n = Int(CommandLine.arguments.dropFirst().first ?? "")!
print(String(fib(num: n)))
/*
example
JITmode:
swift fib_swift.swift 39
compile:
swiftc -O -o fib_swift fib_swift.swift
run:
./fib_swift 39
*/
Kotlin
Android向けの開発で主流になりそうな言語。
別にJavaでええやんって思うけど、Google様がそうじゃないとおっしゃったのならそうなのでしょう。
まぁ、Javaよりもすっきりかけるような気はします。
Kotlin/Nativeといって、Android以外でもネイティブコードを出力できる実装もあります。
// フィボナッチ数 by Kotlin
fun fib(n: Int) : Int {
return if (n < 2)
n
else
fib(n - 2) + fib(n - 1)
}
fun main(args: Array<String>) {
val n:Int = args[0].toInt()
println(fib(n))
}
/*
example
native code
compile:
kotlinc-native fib.kt -o fib
run:
./fib.kexe 39
byte code
compile:
kotlinc fib.kt -include-runtime -d fib.jar
run:
kotlin fib.jar 39
*/
Octave・Scilab
なんでいきなり数値計算システムが出てきたかというと、TIOBEでは、この位置に「MATLAB」が来ていたため。
というか普通の言語が続いたので、少し気分転換に。
肝心のMATLABが手元にないため、Octave、Scilabでお茶を濁します。
さすがは数値計算が専門の言語。
数値演算のプログラムはすっきり書けます。
ただし、実効速度は遅い。
あと、Scilabをコマンドラインから引数を取得して実行する方法は調査中。
Octave
# フィボナッチ数 by Octave
function f = fib(n)
if (n<2)
f = n ;
else
f = fib(n - 2) + fib(n - 1);
endif
endfunction
args = argv();
printf("%d", fib(str2num(args{1})));
#{
example
run:
octave-cli -qf fibonacci.m 20
#}
Scilab
-->function f = fib(n)
--> if n < 2 then
--> f = n
--> else
--> f = fib(n - 2) + fib(n - 1)
--> end
-->endfunction
-->fib(20)
ans =
6765.
Groovy
なまけものの為のJava。Javaが故にJavaとの親和性も高い。
コンパイルしなくても動いちゃう。変数の型とか指定しなくても動いちゃう。
でも真面目に型指定とかしてあげるとちゃんと高速で動きます。
嫌いじゃないけど、クセがなさすぎて使いどころに迷います。
でも、int をIntegerって書いちゃうとすごく遅くなったりとか、しれっと罠が潜んでいるので注意。
// フィボナッチ数 by groovy
int fib(int n) {
if (n < 2) {
return n;
} else {
return fib(n - 2) + fib(n - 1);
}
}
int n = Integer.decode(args[0]);
println fib(n);
/*
example
run source code:
groovy fib_groovy.groovy 39
compile:
groovyc fib_groovy.groovy
run byte code:
groovy fib_groovy 39
*/
R
数値計算用言語。
と言っても行列とか集計とかが書きやすいってだけで、ゴリゴリの数値演算は遅い。
速度を求めるなら、CとかFortanとか使いなさいということだと思います。多分。
ググりにくい。
# フィボナッチ数 by R
fib <- function(n) {
if (n < 2)
return(n)
else
return(fib(n - 2) + fib(n - 1))
}
argv <- commandArgs(TRUE)
n <- as.integer(argv[1])
cat(fib(n))
# example
# run:
# Rscript fibonacci.R 30
D
Cの置き換えを目指して作られた言語(だと思います)。
C++やJavaのいいとこ取りをして高機能にしたら、実装が追いついていない印象。
来るぞ来るぞと言われて一向に来ない。多分来ません。
本家のコンパイラより、GNUのコンパイラの方が速い始末。
// フィボナッチ数 by D
import std.stdio;
import std.conv;
int fib(int n) {
if (n < 2) {
return n;
} else {
return fib(n - 2) + fib(n - 1);
}
}
void main(string[] args) {
int n = to!int(args[1]);
writeln(fib(n));
}
/*
example
compile:
dmd fib_d.d -O -inline
gdc -O3 fib_d.d
run:
./fib_d 39
*/
FORTRAN
2016年のフィボナッチ数の演算では最速をマークした言語。GNUのコンパイラではCより速いときもあります。
歴史の古さ、性能の高さ、難解そうなイメージ、スパコンでの実績など文句なく最強言語の一つ。
実はBasicはFortranを簡単にしたものなので、初見でもなんとなく読める言語。
古い実装ゆえ、最近流行りの機能はあまりありませんが、そこが魅力。
FORTAN90で書いてみました。
program main
implicit none
character(255) a
integer n
call getarg(1, a)
read(a,*) n
print *, fib(n)
contains
recursive integer function fib(n) result(ret)
integer n
if (n < 2) then
ret = n
else
ret = fib(n-2) + fib(n-1)
end if
end function fib
end program main
! compile example
! gfortran -o fib_fortran -O3 fibonacci.f90
Dart
最近気になる言語No.1(調査人数1人)。
スクリプト言語の中ではダントツに速い。ヘタなコンパイル言語に匹敵する速さ。
静的型付け言語。
しかし、インストールしたままの状態だと、Google Analyticsにレポートを送信するなど、
セキュリティ的に謎挙動がありそうなので使用には注意が必要そう。
実行するときに1秒ほど待たされされる時があり、なんか信用ならない。
// フィボナッチ数 by Dart-2.12.0
int fib(num n) {
if (n < 2) {
return n;
} else {
return fib(n - 2) + fib(n - 1);
}
}
void main(List<String> arguments) {
int n = int.parse(arguments[0]);
print(fib(n));
}
/*
example
run:
dart fibonacci.dart 39
*/
Lisp
難解そうなイメージではトップクラスの関数型言語。
憧れはあるのだが、いつもカッコの多さの前にくじけてしまう。
Steel Bank Common Lisp で試してみました。
Clispで動くようにもしてみたつもりだけど試していません。
(defun args()
#+sbcl sb-ext:*posix-argv*
#+clisp ext:*args*
)
(defun fib (n)
(if (< n 2)
n
(+ (fib (- n 2)) (fib (- n 1)))
)
)
(defun main()
(print (fib (parse-integer (nth 1 (args)))))
)
(main)
#|
example
run:
sbcl --script fib_lisp.cl 39
|#
Ada
アメリカ国防総省の要求により開発された超硬派言語。
歴史は古いがパッケージ等の概念があります。
あまりに文法に厳密にしたため、一般うけしませんでした。
今でも使われているのでしょうか?
GNUではgnatとして実装されています。GNU Cよりも速いことがあります。
with
Ada.Integer_Text_IO,
Ada.Command_Line;
use
Ada.Integer_Text_IO,
Ada.Command_Line;
procedure fib_ada is
N : Integer := Integer'value(Argument(1));
begin
declare
function fib (n : Integer) return Integer is
begin
if n < 2 then
return n;
else
return fib(n - 2) + fib(n - 1);
end if;
end fib;
begin
Put(fib(N), 1);
end;
end fib_ada;
-- example
-- compile
-- gnatmake -O3 fib_ada.adb
Scratch
MITによって開発されたブラウザ上で動作する言語。
本当は教育用でタートルグラフィックスとかをやる言語だと思いますが、数値演算もできないではありません。
JavaScriptを呼び出せるので、本当はそっちでやるべきだと思います。
ダウンロードしてローカル環境で遊ぶこともできる。癖になると楽しい。
Scratch本家ではなく、Snap!というサイトで遊んでみました。
Spidermonkeyのおかげだと思うが、Octaveより速い。 Octaveが改善されました。
Scala
Java で実装された関数型言語。
インタプリタのオーバーヘッドが大きいのか、軽い処理が遅い。
重い処理では限りなくJava の速度に近づく。
文法はかなりすっきりしています。
関数でパターンマッチングが使えるのは素敵ですが、if の方が速いのが残念。
// フィボナッチ by Scala
object fib_scala {
def fib(n: Int): Int =
if (n < 2)
n
else
fib(n - 2) + fib(n - 1)
/* こっちが遅い
def fib(n: Int): Int = n match {
case 0 => 0
case 1 => 1
case _ => fib(n - 2) + fib(n - 1)
}
*/
def main(args: Array[String]) = {
var n = Integer.parseInt(args(0))
println(fib(n))
}
}
/*
example
run as script:
scala -Onone fib_scala.scala 39
compile:
scalac -optimise -target:jvm-1.8 fib_scala.scala
run as byte code:
scala
*/
COBOL
銀行系でぶいぶい言わしてた言語。
新規に学ぶ人が少なくてずいぶん前からプログラマの高齢化が絶賛進行中。
これを憶えるだけで高給取りになるという噂もあるけれど、実際には銀行業務がわかってないとだめです。
全部大文字ってのが時代を感じさせます。
* フィボナッチ数 by GnuCOBOL
IDENTIFICATION DIVISION.
FUNCTION-ID. FIBONACCI.
DATA DIVISION.
LOCAL-STORAGE SECTION.
01 t1 PIC 99.
01 t2 PIC 99.
LINKAGE SECTION.
01 n PIC 99.
01 r PIC 9(8).
PROCEDURE DIVISION USING n RETURNING r.
IF n = 0 THEN
COMPUTE r = 0
ELSE IF n = 1 THEN
COMPUTE r = 1
ELSE
COMPUTE t1 = n - 2
COMPUTE t2 = n - 1
COMPUTE r =
FUNCTION FIBONACCI (t1) +
FUNCTION FIBONACCI (t2)
END-IF.
EXIT FUNCTION.
END FUNCTION FIBONACCI.
IDENTIFICATION DIVISION.
PROGRAM-ID. FIB.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
REPOSITORY.
FUNCTION FIBONACCI.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 A PIC 99.
PROCEDURE DIVISION.
ACCEPT A FROM COMMAND-LINE
DISPLAY FUNCTION FIBONACCI (A).
STOP RUN.
*> Example
*> compile:
*> cobc -x fib.cob
*> run:
*> ./fib 30
Prolog
日本のコンピュータ業界で口にしてはならない言葉があります。
それが「Σ計画」と「第5世代コンピュータ」です。
その「第5世代コンピュータ」を開発するにあたって中核を担っていた言語がPrologです。
別に日本産の言語っていうわけではないです。
そういうわけで不遇なPrologですが、「論理型言語」という特徴的なパラダイムの言語です。
誤解を恐れずに超簡単に省略すると、
「命題を宣言していったら、質問に答えてくれるようになるんじゃね?」
って感じでプログラミングしていきます。
現状、「実用的か?」って聞かれたら即答で「無理。」ですが、研究や学習対象としては非常に面白い言語です。
うっかりするとメモリをバカ食いします。
そもそもこんな計算させるなって話ですが。
GNU Prolog (gprolog)
環境変数GLOBALSZとかTRAILSZとかでメモリ設定しないと大きな引数で動きません。
Prologのソースコードの標準の拡張子が「.pl」なため、Perlと衝突します。
インタプリタはPerlより少し高速で、コンパイルするとRuby程度の速さになります。
% フィボナッチ数 by GNU Prolog
fib(0,0).
fib(1,1).
fib(X,Y) :-
X > 1,
X2 is X - 2, fib(X2, Y2), !,
X1 is X - 1, fib(X1, Y1), !,
Y is Y1 + Y2.
main :- current_prolog_flag(argv, Argv),
nth0(1, Argv, Param),
number_atom(N, Param),
fib(N, X),
write(X),
nl,
halt.
:- initialization(main).
% exapmle
% interpreter:
% export GLOBALSZ=262144;export TRAILSZ=262144; gprolog 30 --consult-file fibonacci.pl
% compiler:
% gplc fibonacci.pl
% export TRAILSZ=1048576; ./fibonacci 39
Lua
流行るかなと思わせておいて、なかなか流行らない言語。
と思いきや、ゲームなどではよく使われていたりします。
知らない間にluajit とか出てるし、速い。
あまりクセのない文法。
-- フィボナッチ数
function fib(n)
if n < 2 then
return n
else
return fib(n - 2) + fib(n - 1)
end
end
n = tonumber(arg[1])
print(fib(n))
--[[
example
lua fib_lua.lua 39
luajit fib_lua.lua 39
--]]
F#
Microsoft Visual Studio の異端児。関数型言語。
異端児が故にドキュメントも少ない。何人使っているのでしょうか。
関数型言語らしく、関数ではパターンマッチが使えます。
フィボナッチ数を求める以外に使いみちがわかりません。
// フィボナッチ数 by F#
(* if else
let rec fib n =
if n < 2 then
n
else
fib(n - 2) + fib(n - 1)
*)
let rec fib = function
| n when n=0 -> 0
| n when n=1 -> 1
| n -> fib(n - 2) + fib(n - 1)
[<EntryPointAttribute>]
let main (args) =
//printf "%d" (fib(10))
let n : int = int args.[0]
printf "%d" (fib(n))
0
(*
example
compile:
fsharpc --optimize+ fib_fs.fs
run:
mono fib_fs.exe 39
*)
Haskell
硬派な関数型言語。硬派といってもLispほどカッコ地獄に陥らない。
個人的には好き。でも使いこなせない自分がはがゆい。
-- フィボナッチ数 Haskell版
import System.Environment (getArgs)
fib :: Int -> Int
fib n
| n < 2 = n
| otherwise = fib(n - 2) + fib(n - 1)
main = do
argv <- getArgs
let n = read (argv !! 0) :: Int
print $ fib n
{-
example
compile:
ghc -O -o fib_haskell fib_haskell.hs
run:
./fib_haskell 39
-}
zipWithを使ってずらしたリストを合成していく方法 -- bra_cat_ket様ありがとうございます。
(たぶんこっちがHaskellらしい書き方)
-- フィボナッチ数 Haskell(zipWith)版
import System.Environment (getArgs)
fib :: Int -> Integer
fib n = fibs !! n
fibs :: [Integer]
fibs = 0:1:zipWith (+) fibs (tail fibs)
main = do
argv <- getArgs
let n = read (argv !! 0) :: Int
print $ fib n
Erlang
下手な説明をするとすごい人に怒られてしまいそうなアーラン。
動的型付けな関数型言語です。
並列処理思考で分散処理指向で…。
すみません、もうこれぐらいで勘弁してください。怒らないでください。
起動するのに1秒程度オーバーヘッドがあるのがつらいとか、
(最近はオーバーヘッドは全然気にならなくなりました)
バイトコードの拡張子が「.beam」ってだっせぇとか、
言いませんからごめんなさい、ごめんなさい。
汚いコード晒してごめんなさい。
% フィボナッチ数 by Erlang
-module(fibonacci).
-export([main/1]).
main(Arg) ->
N = fib(list_to_integer(hd(Arg))),
io:fwrite(integer_to_list(N)).
fib(0) -> 0;
fib(1) -> 1;
fib(N) -> fib(N - 2) + fib(N - 1).
% example
% compile:
% erlc fibonacci.erl
% run:
% erl -noshell -run fibonacci main 39 -run init stop
Elixir
Erlangの仮想マシン上で動く言語です。
Erlangでできることは大抵できるっぽいです。
Erlangよりは書きやすくなってそうですが、そうでもないような気もします。
Erlang同様、関数型言語の書き方なので、わざわざこれにするメリットがあるかどうかわかりません。
「エリクシール」と読みます。HPやMPが回復するかもしれません。
elixircコマンドでバイトコードにコンパイルしておけますが、
コマンドライン引数を使用するようなプログラムは、若干書き方を変えないといけません。
defmodule Fun do
@moduledoc """
フィボナッチ数を計算する`fib/1`を提供
"""
@doc """
フィボナッチ数を計算します。
## パラメータ
- n: integer
## 例
実行環境がUTF-8じゃないと動きません。
export LANG=ja_JP.UTF-8
elixir fib.ex 10
"""
def fib(0), do: 0
def fib(1), do: 1
def fib(n) do
fib(n-2) + fib(n-1)
end
end
[arg1] = System.argv()
IO.puts Fun.fib(String.to_integer(arg1))
Rust
Mozillaによって開発されている並列処理が得意な言語。
でもフィボナッチ数には並列処理は不要。
Swiftを凌ぐ速度を出しながら、いまいち注目されない言語。
(最近ようやく注目され始めた?)
しかもちょっと似ています。
// フィボナッチ数 by rust
use std::env;
fn fib(n: i64) -> i64 {
if n < 2 {
n
} else {
fib(n - 1) + fib(n - 2)
}
}
fn main() {
if let Some(s) = env::args().nth(1) {
if let Ok(n) = s.parse::<i64>() {
println!("{}", fib(n))
}
}
}
/*
example
compile:
rustc -C opt-level=3 fib_rust.rs
run:
./fib_rust 39
*/
Clojure
JavaVM上で動くLisp系の関数型言語。
.Net環境でも動くらしいことを聞いたけど詳しいことは知りません。
やはりLisp系。括弧地獄です。
てか、今回のサンプルではほぼLispと同じです。
; フィボナッチ数 by Clojure
(defn fib [n]
(if (< n 2)
n
(+ (fib (- n 2)) (fib (- n 1)))))
(println (fib (Integer/parseInt (nth *command-line-args* 0))))
(comment
example
run
clojure -M fib.clj 30
)
これより以下は2016年頃のTIOBEのランキング外の言語
Go
Google謹製の言語。最近はあまりニュースがありませんが、
確実にユーザーは増えているようです。
いい言語なんですけどね。
2016年頃は不遇な時期でした。2022年の時点では人気のある言語です。
依存するライブラリがなくシングルバイナリで実行できるようになるのが何気にすごい。
<再帰関数版>
// フィボナッチ数 by Go
package main
import "fmt"
import "flag"
func fib(n int) int {
if n < 2 {
return n
} else {
return fib(n-2) + fib(n-1)
}
}
func main() {
var n = flag.Int("n", 0, "usage")
flag.Parse()
fmt.Println(fib(*n))
}
/*
example
compile:
go build fib_go.go
run:
./fib_go -n 39
*/
<メモ化関数版>TakaakiFuruse 様ありがとうございました。
// フィボナッチ数 メモ化 by Go
package main
import "fmt"
import "flag"
func calcFib(n int) int {
fib := []int{0, 1}
for i := 1; i < n; i++ {
f := fib[len(fib)-1] + fib[len(fib)-2]
if f == n {
break
}
fib = append(fib, f)
}
return fib[len(fib)-1]
}
func main() {
var n int
flag.IntVar(&n, "n", 0, "usage")
flag.Parse()
fmt.Println(calcFib(n))
}
/*
example
compile:
go build fib_go.go
run:
./fib_go -n 39
*/
julia
ここ数年でPythonほどではありませんが注目されるようになった言語。
速度などの改善も著しく、今最も伸びている言語のひとつだと思います。
C、C++、Scheme で実装されたちょっと関数型言語。
Google V8 と同等の速さ。
VM の起動の遅さを抱えていましたが、最近はかなり改善されています。 気になりません。
研究者(なんの?)の間で人気らしいです。
行列の計算とかがすごい楽なので、ライブラリさえ充実していれば、
個人的には Python + NumPy よりも、こちらを使いたい。
# フィボナッチ数 by julia-1.7.0-DEV
function fib(n)
if n < 2
return n
else
return fib(n - 2) + fib(n - 1)
end
end
n = parse(Int32, ARGS[1])
println(fib(n))
#=
example
julia -O -- fibonacci.jl 39
=#
# フィボナッチ数 by julia
# もうすこしJuliaっぽく書いてみた。
# 実行速度は多分変わらない。
fib(n) = begin
n < 2 && return n
fib(n - 2) + fib(n - 1)
end
n = parse(Int32, ARGS[1])
println(fib(n))
#=
example
julia -O -- fib_julia2.jl 39
=#
# フィボナッチ数 by julia
# 行列による漸化式
fib(n) = ([1 1;1 0]^n)[1,2]
n = parse(Int32, ARGS[1])
println(fib(n))
#=
example
julia -O -- fib_julia3.jl 39
=#
# フィボナッチ数 by julia
# 一般項による近似式
using Base.MathConstants
fib(n) = floor(Int, φ ^ n / √5 + 0.5)
n = parse(Int32, ARGS[1])
println(fib(n))
#=
example
julia -O -- fib_julia4.jl 39
=#
Maxima
Mathematica に似た数式処理システム。
今回のサンプルの中では唯一組み込み関数でfib()が存在していました。
コマンドライン引数の渡し方がわからなかったのでevalに相当するものを渡すという危険なやり方で妥協。
/* フィボナッチ数 by Maxima */
fib(n) := if n < 2 then n else fib(n - 2) + fib(n - 1);
/*
example
run:
maxima --very-quiet --init-mac fibonacci.mac --batch-string="fib(10);"
*/
<いやぁ、組み込み関数あるんだからプログラム書かなくていいんじゃね?版>
maxima --very-quiet --batch-string="fib(10);"
これなら、引数が100でも1000でも一瞬で結果がでます。
Wolfram (Mathematica)
教育向け数式処理界では最強と噂のMathematica。
一般向けライセンスが高価なため学校の授業以外ではあまり使われていません。
<再帰関数版>
(* フィボナッチ数 by wolfram *)
fib[0] := 0
fib[1] := 1
fib[n_] := fib[n - 2] + fib[n - 1]
n = ToExpression[$ScriptCommandLine[[2]]]
Print[fib[n]]
(* Example *)
(* Run: *)
(* WolframScript -script fibonacci.m 30 *)
<メモ化関数版>
再帰関数をちょっといじっただけ。こういうところが関数型言語の楽しいところ。
(* フィボナッチ数 by wolfram *)
fib[0] := 0
fib[1] := 1
fib[n_] := fib[n] = fib[n - 2] + fib[n - 1]
n = ToExpression[$ScriptCommandLine[[2]]]
Print[fib[n]]
(* Example *)
(* Run: *)
(* WolframScript -script fibonacci.m 30 *)
Nim(旧Nimrod)
日本語版のWikipediaが無いという珍しい言語(2016年1月現在)
(2016年8月、Wikipediaに追加されたようです。)
C経由でネイティブコードを吐くらしいのですが、何故かCより速かったりします。
いつか使いたい。いつかね。
# フィボナッチ数 by Nim
import os
import strutils
proc fib(n: int): int =
if n < 2:
return n
else:
return fib(n - 2) + fib(n - 1)
var n = parseInt(paramStr(1))
echo(fib(n))
discard """
example
compile:
nim compile --opt:[none|speed|size] fib_nim.nim
run:
./fib_nim 39
"""
OCaml
海外ではなぜか人気のない関数型言語。
スクリプトモードでもそこそこ速いけど、ocamlopt でネイティブコードにコンパイルするとめっさ速くなる。
Ocaml を使ってWEBサイトを立ち上げるのが夢。
(OcamlのWEBサーバーみたいなのもありましたが、思ってるのとちょっと違いました)
<手続きっぽい版>
(* フィボナッチ数 by OCaml *)
let rec fib(n) =
if n < 2 then
n
else
fib(n - 2) + fib(n - 1)
;;
let n = int_of_string Sys.argv.(1);;
print_int(fib n);;
(* example
interpreter:
ocaml fib.ml
compile:
ocamlc -o fib_ocaml fib.ml
compile (native):
ocamlopt -o fib_ocamlopt fib.ml
*)
<パターンマッチング版>
こっちの方が頭よさそうに見えるかも。
(* フィボナッチ数 by OCaml *)
let rec fib n = match n with
0 | 1 -> n
| n -> fib(n - 2) + fib(n - 1)
;;
let n = int_of_string Sys.argv.(1);;
print_int(fib n);;
(* example
interpreter:
ocaml fib.ml
compile:
ocamlc -o fib_ocaml fib.ml
compile (native):
ocamlopt -o fib_ocamlopt fib.ml
*)
Smalltalk
歴史は古く他の言語のモデルとされながらも、クセの強い文法が個性的なため普及しているとは言いがたい。
単なる言語だけではなく「Smalltalk環境」として実装されてきたため、一般のプログラミング言語のような普及の仕方ではありません。
その「環境」を完全に無視したGNU Smalltalk で試してみました。
"フィボナッチ数 by Smallalk"
Integer extend [
fib [
self < 2
ifTrue: [ ^self ]
ifFalse: [ ^(self - 2) fib + (self - 1) fib ].
]
]
Smalltalk arguments first asInteger fib printNl.
"example
run:
gst fibonacci.st -a 39
"
Forth
スタック型言語。後置記法になるため、ぱっと見何が書いてあるのかわからないコンピュータ(コンパイラ)に優しい言語。
これが書けたらみんなから「変態」の称号がもらえるありがたい言語。
<再帰関数版>
\ フィボナッチ数(再帰版) by forth
: fib ( n )
dup 2 u< if exit then
1- dup recurse swap 1- recurse + ;
fib . cr
bye
(
example
run:
gforth -e 39 fibonacci.fs
gforth-fast -e 39 fibonacci.fs
)
<ループ版>
\ フィボナッチ数(ループ版) by forth
\ 2以下を与えるとエラー(テヘ♪
: fib ( n -- n )
0 1
2 roll 1 - 0 do
2dup +
2 roll drop
loop
nip
;
fib . cr
bye
Mind
スタック型言語の特徴をうまく(?)利用した日本語によるプログラミング言語。
「ぴゅう太日本語BASIC」以来の衝撃を受けた言語。
しばらく開発が止まっていましたが、最近Androidで動かすプロジェクトがあるらしいです。
2021年にバージョンアップされてました。相変わらず文字コードはEUC-JPですが。
(フィボナッチ by Mind)
フィボナッチとは (数値 → 数値)
値1は 変数
値1に 入れ
値1が 1 以下 ならば
値1を 返す
さもなければ
値1から 2を 引き フィボナッチし
値1から 1を 引き フィボナッチし
足して 返す
つぎに
。
メインとは
起動引数(1)を 数値変換して 真? ならば
フィボナッチして
数値表示
つぎに
。
※example
※ compile:
※ mind fib_mind.src file
※ run:
※ ./fib_mind 39
APL
ネタ言語(Brainf**k等)を除き、変態度では他の追随を許さないプログラミング(?)言語。
特殊な記号を多用するため集約度は高いですが、
プログラミング言語のクセにプログラミングされることを拒絶する仕様。
APLで使用する記号はUTF-8に登録されましたが、似た記号が多く入力の難しさは改善されていません。(むしろ改悪されました)
また表示されていてもそれが文字化けなのか正しいものなのかはAPLをマスターしないとわかりません。
コードを眺めているとゲシュタルト崩壊を起こします。
結局はキーボードで入力可能なJ言語が開発されましたが、興味のある方は変態道を突き進んでAPLをマスターして欲しいと思います。
しかし、FORTRANとほぼ同じ1957年にリリースされた事を考えると、正直化け物じみています。
オーパーツです。
GNU APL
<再帰関数版>
#!/usr/bin/apl --script
∇R←fib N
→L+(N>1)
L:R←N ⋄ →0
R←(fib (N - 2)) + fib (N - 1)
∇
fib ⍎⍕¯1↑⎕ARG
)OFF
⍝ example
⍝ run:
⍝ ./fibonacci.apl -- 20
<行列による漸化式版>
暗号化度さらにUP
#!/usr/bin/apl --script
∇R←fib N
R←↑0 1↓↑+.×/N/⊂2 2⍴1 1 1 0
∇
fib ⍎⍕¯1↑⎕ARG
)OFF
⍝ example
⍝ run:
⍝ ./fibonacci.apl -- 20
Dyalog・NASR2000
fib←{⍵≤2:1 ⋄ (∇⍵-1)+∇⍵-2}
で定義できますが、顔文字にも見えます。
Pike
スクリプトのクセに静的型付けな言語です。Cっぽいです。
そのおかげなのかそこそこ速いです。
以前からRubyと同じぐらいの速度を維持しており、むしろRubyが指標としているのではと思わせるほど。
// fibonacci by Pike-8.0
int fib(int n)
{
if (n < 2) {
return n;
} else {
return fib(n-2)+fib(n-1);
}
}
int main(int argc, array(string)argv)
{
int n;
n = (int)argv[1];
write("%d", fib(n));
return 0;
}
/*
example
run:
pike fibonacci.pk 39
*/
io
Smalltalkに強く影響を受けた純粋なオブジェクト指向言語。
そのため、メッセージパッシングという考え方が結構支配的。
コルーチン、アクター、フューチャーといった並列処理のための仕組みが実装されている。
もちろん自分は使いこなせていない。
実行速度はあまり速くはないけど、並列処理入門としてはいいかもしれないし、
そうではないかもしれない。
多分読み方は「アイ・オー」ではなく「イオ」
Googleで検索しにくい。
あと、公式サイトがやたらかっこいい。
https://iolanguage.org/
// フィボナッチ数 by io
fib := method(n,
if (n < 2,
n,
fib(n - 2) + fib(n - 1)
)
)
fib(System args at(1) asNumber) println
/*
example
run:
io fib.io 30
*/
Icon
ゴール指向評価という「成功」か「失敗」による制御構造を特徴とする言語。
真偽値による評価とどう違うのかと聞かれるとちゃんと答えられませんが、
「if a < b < c」とか気持ち悪いif文が書けます。
他にもジェネレータが強力だったり、リストや連想配列、集合、レコード型などデータ構造も豊富。
手続きそのものを変数にぶちこめる「コ・エクスプレッション」という関数型言語っぽいこともできるそうなのですが、試していません。
そもそも今回のサンプルではそれらの特徴をまったく活かせてません。
面白そうな言語ではありますが。
icontコマンドで実行形式のバイナリにできますが、速度はまったく変わりません。
なお、Wikipediaなどのリンクが古くなっている模様。
http://www2.cs.arizona.edu/icon/
↑が生きています。
アリゾナ大学のサイトで「Past Research Projects」に入っちゃってますが、何かあったのでしょうか?
サイトの更新は2016年現在も続いているようです。
# フィボナッチ数
procedure fibonacci(n)
if n < 2 then
return n
else
return fibonacci(n - 2) + fibonacci(n - 1)
end
procedure main(args)
local n
n := args[1]
write(fibonacci(n))
end
# example
# interpreter:
# icon fibonacci.icn 39
# translator:
# icont fibonacci.icn
# ./fibonacci 39
Qiitaのコードハイライトが対応していません。
Occam
英語も日本語もドキュメントが少ない上に、めちゃくちゃ検索しづらいです。
たぶん「終わった言語」です。
1980年代に次世代のマイクロプロセッサとして並行コンピューティングに特化したアーキテクチャである「トランスピュータ」のために開発された「CSP」をより実用的に拡張した言語です。
そういった出自ゆえ並列処理が得意で、「PAR」とか「SEQ」とかのキーワードで積極的に並列処理と逐次処理を指定できたりするところも面白いです。
並列処理とプロセス間のメッセージやり取り以外は、普通に手続き型の言語です。
コマンドが大文字というところが時代を感じさせます。
ブロックはPython同様のインデント形式ですが、きっちり2文字ずつじゃないと怒られます。
並列処理向けの言語として将来再び注目されるかもしれませんし、されないかもしれません。
KRoc (Occam-π)
ケント大学によって開発されたOccamのコンパイラ。
開発は終わってるっぽいですが、たまにgitが更新されています。
インストーラやビルドツールにPythonが使われていますが、Python3で動きません。
いらっとします。
コマンドライン引数を取得する方法を調べるのに挫折しました。
なお、言語の名称を「おっπ」とか省略してはいけません。
-- フィボナッチ数 by Occam
#INCLUDE "course.module"
INT REC FUNCTION fib (VAL INT n)
INT res:
VALOF
IF
n < 2
res := n
TRUE
res := fib (n - 2) + fib (n - 1)
RESULT res
:
PROC fibonacci (CHAN BYTE out)
out.int (fib(39), 0, out)
:
-- example
-- compile:
-- occbuild --program fibonacci.occ
-- or
-- kroc fibonacci.occ
-- run
-- ./fibonacci 39
Chapel
アメリカ国防高等研究計画局の高生産性計算機システムプロジェクトです。
スーパーコンピューターのCRAYです。
もうコレだけで強うそうでしょ?
「Chapel」は「Cascade High Productivity Language」の略で、日本語にすると
「多段高生産性言語」だそうです。
厨二ゴコロにどストライクです。
並列計算機「Cascade」のプログラム開発効率を改善するために作られたコンパイラです。
なので前述のOccam同様、並列計算向きの言語です。
もちろんフィボナッチ数のサンプルについてはそこんとこまったく使っていません。
プログラミング効率を上げるためのオブジェクト指向や現代的で見慣れた文法を採用することで、硬派な割にはとっつきやすい感じになっています。
プロジェクト自体は2010年に終了していますが、現在もオープンソースプロジェクトとして開発は絶賛継続中で、CRAY社のホームページで公開されています。
もっと注目されてもいい言語だと思うのですが…。
しかし、フィボナッチ数のサンプルをコンパイルすると3.1MBあります。
// フィボナッチ数 by Chapel
proc fib(n: int): int {
if (n < 2) {
return n;
} else {
return fib(n - 2) + fib(n - 1);
}
}
proc main(args: [] string) {
var n: int = args[1]:int;
writeln(fib(n));
}
/*
example
compile:
chpl -o fibonacci fibonacci.chpl
run:
./fibonacci 39
*/
Oz (Mozart)
Ozはマルチパラダイムでネットワーク透過な分散プログラミングができるらしい。よくわからん。
比較的新しい(最初の設計が1991年)言語なので、実用云々よりは、今後のプログラミングの可能性の一つとして見る分には面白いのではないかと。
ただ、ドキュメントは少なく、やっとたどり着いてもほとんどがemacsの説明だったりします。
Mozart2
Ozの高品位な実装がMozart。Mozart2が出ているが、まだAlpha版。とはいうもののそこそこ動くようです。
Ver.1 はLLVMを使っていたようですが、Ver.2はどうなんでしょう?わかんない。
Ver.2 alpha では、ozc -x でコンパイルしても単独で実行できる形にはならないようです。
「ディレクトリ」に依存しないだけかもしれません。(でもエグゼキュートビットは立ってる)
ozc -c と ozc -x でfunctor の書き方が微妙に違うのは私がわかってないせいだと思います。
% フィボナッチ数 by Mozart2(Oz)
functor
import
System
Application
prepare
fun {Fib N}
if N < 2 then
N
else
{Fib N - 2} + {Fib N - 1}
end
end
define
N in
[N] = {Application.getArgs plain}
{System.showInfo {Fib {String.toInt N}}}
{Application.exit 0}
end
/*
example
compile:
ozc -c fibonacci.oz
run:
ozengine fibonacci.ozf 39
*/
fun {Fib N] を fun lazy {Fib N} に書き換えると遅延評価の関数になります。
このサンプルだと遅くなっちゃいました。
Tcl
Tcl はすっごい有能なシェルです。
まず、計算させようとか思ってはいけません。
Tkと合わせればさくっとGUIのアプリケーションが作れます。
しかもLinux と Windows とでほぼ同じソースで。
でも、計算させます。
コメントブロックの書き方が強烈です。(公式な書き方の一つ)
「tcl::mathfunc::」をつけないと再帰呼び出しできないようです。
10分ハマりました。
# フィボナッチ数 by Tcl
proc tcl::mathfunc::fib {n} {
if {$n < 2} {
return $n
} else {
return [expr fib([expr {$n - 1}]) + fib([expr {$n - 2}])]
}
}
set n [lindex $argv 0]
puts [expr fib($n)]
if 0 {
example
run:
tclsh fibonacci.tcl 10
}
Neko
かつてはHaxeを動かすためのVMにもなっていましたが、今はHashLinkにあとを譲り、ゆっくり余生を過ごされている模様。
ネーミングから日本製と思われがちですが、海外製です。
Neko公式サイトを訪れると想像と違うネコさんでした。
言語的には癖のない手続き型言語です。
// フィボナッチ数 by Neko
fib = function(n) {
if( n < 2 )
return n
else
return fib( n - 2 ) + fib( n - 1);
}
n = $int($loader.args[0]);
$print( fib( n ) );
/*
example
compile:
nekoc fib.neko
run:
neko fib.n 39
*/
V
Goをシンプルにしたような言語。
コードもすっきりしているような気がします。
2022年時点ではバージョンもまだ若く、インストーラなど粗削りな感じも否めませんが、今後、場合によっては化けるかも知れません。
// フィボナッチ数 by V
import os
fn fib(n int) int {
if n < 2 {
return n
} else {
return fib(n - 2) + fib(n - 1)
}
}
fn main() {
n := os.args[1].int()
println(fib(n))
}
/*
example
script:
v run fib.v 10
compile:
v fib.v
run:
./fib 39
*/
Euphoria
シンプルな型と洗練された構文の手続き型言語。
なのであまり特徴がありません。
C言語へのトランスレータ機能があるらしいのですが、
サンプルコードではうまく動きませんでした。
-- フィボナッチ数 by Euphoria
include std/convert.e
function fib(integer n)
if n < 2 then
return n
else
return fib(n - 2) + fib(n - 1)
end if
end function
sequence cmd = command_line()
integer n = to_integer(cmd[3])
puts(1, to_string(fib(n)))
/*
example
run:
eui fib.e 30
*/
REXX
かつての大巨人IBM様の生み出した言語です。
文法的には今となっては普通なのですが、当時としてはすごかったのかもしれません。
見どころは、出力が「say」
/* フィボナッチ数 by REXX */
say fib(arg(1))
exit
fib: procedure
parse arg n .
if n < 2 then
n = n
else
n = fib(n - 2) + fib(n - 1)
return n
/*
example
run:
rexx fib.rexx 30
*/
Squirrel
ゲームの組み込みなどに使うことを目的とされ開発された言語。
立ち位置がLuaとかぶってます。
速度的には、Luaにちょっと置いて行かれた感じ。
構文的にはLuaよりも厳しく、バグが出にくい仕様にはなっています。
ドキュメントが少なく、ググりにくいのもつらい。
// フィボナッチ数 by Squirrel
function fib(n)
{
if (n < 2)
return n;
else
return fib(n - 2) + fib(n - 1);
}
local n = vargv[0].tointeger()
print(fib(n).tostring() + "\n");
/*
example
run
sq fib.nut 39
*/
Ring
めずらしく中東生まれの言語。おそろしく書き方が自由なため、複数人での開発とか苦労しそう。
言語の開発者は「}」とか「;」とか、あと「改行」すら嫌いだったんだと思います。
サンプルは見やすくするように改行とインデントつけてますが、ずらずらーと1行に書いても動きます。
用途としてはOpenGLを使ったゲームなどを想定しているようです。
言語単体としては遅いです。
// フィボナッチ数 by Ring
func fib n
if n < 2
return n
else
return fib(n - 2) + fib(n - 1)
ok
func main
n = Number(SysArgv[3])
see fib(n)
/*
example
ring fib.ring 30
*/
おまけ(ネタ枠)
dc
これまた検索しにくい言語?ですが、Linuxでほぼ標準でついてくるRPN(逆ポーランド記法)のコマンドライン計算機です。再帰可能なマクロも書けます。
レジスタのセーブとロードが前置記法になっているのが気に入りませんが…。
dcを使ったフィボナッチ数のサンプルはまだ見たことがありません。
限りなくネタ言語ですし、まぁ、やる人はあまりいないでしょうけど。
遅いです。
# フィボナッチ数 by dc
sa
[2Q] s.
[d 2 >. 1 - d lfx r 1 - lfx +] sf
la lfx p
# example
# run:
# dc -e 30 fibonacci.dc
bc
dcを出したならこっちも出しとかなきゃと思って出しました。
dcが親分なのか、こっちがそうなのかはしりません。
こっちは普通の中置記法の計算機です。
bashに埋め込んだりもできます。
コマンドライン引数を取得する方法がわからなくて、ずるしました。
#!/bin/bash
bc -q <<EOF
# Fibonacci Numbers
define fib(n) {
if (n < 2) {
return n
} else {
return fib(n - 2) + fib(n - 1)
}
}
n = $1
print fib(n)
quit
/*
example
bash fib.sh 30
*/
EOF
Bash
大事なもの忘れてました。
Linuxを操作するのにほぼ必須なBash。
再帰関数呼び出しもできるシェル。すっごい有能だと思いませんか?
Tcl「・・・」
でも試すときは引数を少しずつ大きくしていってくださいね。
私は「20」で危険を感じました。
# フィボナッチ数 by bash
#!/bin/bash
fib () {
if [ $1 -lt 2 ]; then
echo $1
else
echo $(($(fib $(($1-2)))+$(fib $(($1-1)))))
fi
}
echo $(fib $1)
# example
# run:
# ./fibonacci.sh 20
arturo
「コードはアートだ」と言い切るいさぎよさ。
2019年に始まった若いプロジェクトですが、Linux以外にもさまざまなプラットフォームで動作します。
むしろ、そのせいで実行速度が犠牲になっているのではないかと…。
Arturo公式サイトも今風です。
サイト上では「→」なんか使っちゃったりしてますが、ソースコードで本当に全角の「→」使うと怒られます。
「->」です。
式も右結合だったりと、ちょっと個性的な言語です。
; フィボナッチ数 by arturo
fib: function [n][
if? n < 2 -> n
else -> (fib n - 2) + fib n - 1
]
n: to :integer arg\0
print fib n
; example
; arturo fib.art 20
;
Windows Powershell
Windowsだってシェルっぽいことできるもん!
で、実装されたWindows Powershell。
「うぉお!lsコマンド使えるじゃん!」というところまではいいのですが、
実際スクリプトファイル書こうとすると全然別物です。
シェルっぽいことやりたければ、Cygwin入れればいいと思います。
実行速度は、遅いです。
Param($n)
function Fib ($n) {
if ($n -lt 2) {
Write-Output $n
} else {
Write-Output ((Fib ($n - 2)) + (Fib ($n - 1)))
}
}
Write-Host (fib $n)
<#
example
Set-ExecutionPolicy RemoteSigned -Scope Process
./fibonacci.ps1 20
#>
Linotte
フランス語による教育向け言語。Java製。
なんかかっこよさそうなのでエントリー。
見かけはすっきりしてて好き。
でも遅い
ターミナルで実行する方法がわからん。
あと「é」の入力方法がわかりません。
principale :
n est un nombre
début
affiche "Input Number[1-25]"
demande n
affiche fib(n)
fib :
*n est un nombre
début
si n < 2 retourne n
sinon retourne fib(n - 2) + fib(n - 1)
Flowgorithm
プログラム学習環境です。
結構楽しい。
動作速度?聞かないで…
いろんな言語の疑似コード等も表示してくれます。
実行速度比較
システム構成
CPU:Intel(R) Core(TM) i7-3930K CPU @ 3.20GHz
メモリ:32GB(速度とか忘れました)
OS:Arch Linux Kernel-4.4.1 SMP x86_64
(※更新中)
CPU:Intel(R) Core(TM) i9-10900K CPU @ 3.70GHz(うち4コア)
メモリ:64GB DDR4(うち16GB)
OS:ArchLinux Kernel 5.17.2 on VirtualBox (Host: Windows 10)
頭の悪い再帰関数で39番目の値「63,245,986」を求める時間です。
コンパイルオプションは適当に何種類か試して速かったものを採用しました。
関数呼び出しのコストぐらいしかわからないかも。
他のアルゴリズムだと大体瞬殺なので面白くありません。
2022 順位 |
2016 順位 |
言語 | バージョン | 実行時間 | バージョン | 実行時間 |
---|---|---|---|---|---|---|
1 | 3 | Basic (fbc -O3) | 1.04 | 0.184 | 1.09.0 | 0.089 |
2 | 5 | Ada (gnat -O3) | 5.3.0 | 0.194 | 11.2.0 | 0.092 |
3 | 7 | C (gcc -O3) | 5.3.0 | 0.255 | 11.2.0 | 0.100 |
4 | 6 | C++ (g++ -O3) | 5.3.0 | 0.252 | 11.2.0 | 0.100 |
5 | 2 | D (gdc -O3) | 5.3.0 | 0.179 | 11.2.0 | 0.107 |
6 | 3 | Nim (-d:release) | 0.12.0 | 0.184 | 1.4.8 | 0.118 |
7 | 11 | Rust (rustc -C opt-level=3) | 1.5.0 | 0.358 | 1.60.0 | 0.122 |
8 | 1 | Fortran (gfortran -O3) | 5.3.0 | 0.146 | 11.2.0 | 0.135 |
9 | 10 | C (clang -O) | 3.7.0 | 0.357 | 13.0.1 | 0.154 |
10 | 12 | Swift (swiftc -O) | 2.2-dev | 0.361 | 5.6 | 0.203 |
11 | 8 | OCaml (ocamlopt) | 4.02.3 | 0.302 | 4.13.1 | 0.205 |
12 | 14 | Crystal (--release) | 0.10.1 | 0.395 | 1.4.0 | 0.208 |
13 | 9 | Java (Open JDK) | 1.8.0 | 0.303 | 11.0.15 | 0.209 |
14 | 13 | Go | 1.5.2 | 0.388 | 1.18.1 | 0.213 |
15 | Kotlin/Native | 1.6.20 | 0.214 | |||
16 | 15 | Pascal (fpc -O4) | 3.0.0 | 0.405 | 3.2.2 | 0.256 |
17 | 22 | Haskell (ghc -O2) | 7.10.3 | 0.570 | 9.0.2 | 0.273 |
18 | 17 | C# (mono -optimize+) | 2.2.2.0 | 0.442 | 6.12.0.0 | 0.291 |
19 | 20 | D (dmd -O -inline) | DMD64 v2.069 | 0.513 | 2.099.0 | 0.311 |
20 | Kotlin(bytecode) | 1.6.20 | 0.321 | |||
21 | 23 | julia (-O3) | 0.4.5 | 0.711 | 1.7.2 | 0.340 |
22 | 18 | Basic (mono /optimize+) | 0.0.0.5943 | 0.485 | 0.0.0.5943 | 0.346 |
23 | 16 | Dart | 1.16.0 | 0.436 | 2.16.2 | 0.362 |
24 | Swift(JIT) | 2.16.2 | 0.421 | |||
25 | 26 | Chapel | 1.13.1 | 0.959 | 1.26.0 | 0.467 |
26 | V(compiled) | 0.2.4 | 0.481 | |||
27 | 19 | Scala(bytecode) | 2.11.8 | 0.490 | 2.13.8 | 0.513 |
28 | 25 | Lua (luajit) | 2.0.4 | 0.897 | 5.4.4 | 0.538 |
29 | 24 | JavaScript (V8) | 4.9.170 | 0.845 | nodejs 17.9.0 | 0.539 |
30 | V | 0.2.4 | 0.631 | |||
31 | 31 | Erlang (erlc) | 19.0.3 | 4.346 | OTP24 | 0.645 |
32 | 29 | Lisp (sbcl) | 1.3.0 | 1.551 | 2.2.2 | 0.833 |
33 | Elixir | 1.13.2 | 1.006 | |||
34 | 21 | JavaScript (SpiderMonkey) | 38.1 | 0.537 | 91.8.0 | 1.142 |
35 | 30 | OCaml (script) | 4.02.3 | 3.389 | 4.13.1 | 1.486 |
36 | Scala | 2.13.8 | 1.515 | |||
37 | 28 | Groovy | 2.4.5 | 1.287 | 4.0.1 | 1.787 |
38 | Clojure | 1.11.1.1105 | 2.063 | |||
39 | 32 | Forth (gforth-fast) | 0.7.3 | 4.792 | 0.7.3 | 2.260 |
40 | 35 | PHP | 7.0.1 | 7.735 | 8.1.5 | 2.407 |
41 | Neko | 2.3.0 | 2.929 | |||
42 | 39 | Lua | 5.3.2 | 10.147 | 5.4.4 | 3.752 |
43 | 33 | Pike | 8.0.182 | 7.205 | 8.0.1738 | 4.153 |
44 | 36 | Smalltalk (gst) | 3.2.5 | 8.098 | 3.2.92 | 4.487 |
45 | 38 | Ruby | 2.3.0p0 | 8.417 | 3.1.2p20 | 4.552 |
46 | 37 | Prolog (gplc) | 1.4.4 | 8.305 | 1.5.0 | 4.642 |
47 | 34 | Mind | 7.20 | 7.325 | 8.07 | 4.845 |
48 | Euphoria | 4.1.0 | 8.193 | |||
49 | Squirrel | 3.2 | 11.057 | |||
50 | 41 | Python | 2.7.11 | 20.680 | 2.7.18 | 11.086 |
51 | 42 | Python | 3.5.1 | 23.375 | 3.10.4 | 11.184 |
52 | 43 | Icon | 9.5.1 | 28.256 | 9.5.21b | 14.577 |
53 | Prolog(SWI-Prolog) | 8.4.2 | 20.105 | |||
54 | 44 | Oz(Mozart) | 2.0.0 aplha | 36.134 | 2.0.1 | 20.545 |
55 | 45 | Perl | 5.22.1 | 56.042 | 5.34.1 | 25.085 |
27 | PHP (hhvm) | 3.13.1 | 1.021 | 4.124.0 | 0.916*1 | |
40 | Occam (KRoC) | 1.6.0 | 11.510 |
*1 Ubuntu20.10で計測
この辺までで39番目の値を求めるのは挫折しました。
ここ以下は予選落ちです。
30番目の値「832,040」を求めた結果です。
比較のためPerlでの実行時間も書いています。
2022 順位 |
2016 順位 |
言語 | バージョン | 実行時間 | バージョン | 実行時間 |
---|---|---|---|---|---|---|
55 | 45 | Perl | 5.22.1 | 0.843 | 5.34.1 | 0.316 |
56 | bc | 1.07.1 | 0.608 | |||
57 | 52 | Perl6 (Rakudo) | 2015.12 | 10.672 | 2022.03 | 0.728 |
58 | 46 | R | 3.2.3 | 2.022 | 4.1.3 | 0.922 |
59 | 48 | dc | 1.3.95 | 2.768 | 1.4.1 | 1.245 |
60 | COBOL(GnuCOBOL) | 3.1.2.0 | 1.822 | |||
61 | io | 2017.09.06 | 2.113 | |||
62 | 49 | Tcl | 8.6.6 | 3.262 | 8.6.12 | 3.126 |
63 | REXX(Regina) | 3.9.4 | 3.472 | |||
64 | 50 | APL (GNU APL) | 1.5 | 6.482 | 1.8 | 3.692 |
65 | 51 | Maxima | 5.37.2 | 10.366 | 5.54.1 | 5.123 |
66 | 54 | Octave (octave-cli) | 4.0.0 | 35.544 | 7.1.0 | 9.016 |
67 | Ring | 1.17 | 13.91 | |||
68 | 53 | Snap! (FireFox 45.0a2) | 4.0.4 | 21.1 | 7.3.1 | 20.5 |
69 | arturo | 0.9.80 | 127.7 | |||
47 | Wolfram (Mathematica) | 10.3 | 2.148 |
数値処理、数式処理の言語が低い順位になっていますが、そもそもこの辺の言語は、アホみたいなアルゴリズムで速度を求めるものではありませんし、それを補ってあまりある高度なグラフ機能等が含まれています。
あとがき
気が向いたら、メモ化する書き方、黄金比から計算する方法、行列から計算する方法も書くかもしれません。
各言語の特徴を活かした書き方もそのうち…。