裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

Rump の例題--その2 Julia の SymPy で解く

2022年09月13日 | ブログラミング

Julia の SymPy は,Python の sympy を利用している。Python の整数型は必要に応じて長精度整数になる。

求める式には実数が含まれるが,この式を 4 倍することで整式になる。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Rump の例題

2022年09月12日 | ブログラミング

Rump の例題
https://www.tuhh.de/ti3/paper/rump/Ru88a.pdf

a = 77617, b = 33096 として,以下の計算を行う

R

f = function(a, b) 333.75*b^6 + a^2 *(11*a^2*b^2 - b^6 - 121*b^4 - 2) + 5.5*b^8 + a/(2*b)
library(gmp)
a = as.bigq(77617)
b = as.bigq(33096)
ans = f(a, b)
as.numeric(ans) # -0.8273960599468214

Julia

f(a, b) = 333.75b^6 + a^2*(11a^2*b^2 - b^6 - 121b^4 - 2) + 5.5b^8 + a/2b
a = big(77617)
b = big(33096)
f(a, b) # -0.8273960599468213681411650954798162919990331157843848199178148416727096930142628

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

Julia 1.8.1 が公開されました

2022年09月11日 | ブログラミング

Julia 1.8.1 が公開されました

 Version 1.8.1 (2022-09-06)

Official https://julialang.org/ release

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

AWK と R のコラボレーション 定式化された入力ファイルからデータファイルへ

2022年09月07日 | ブログラミング

一般解は

https://stackoverflow.com/questions/69385888/parse-multi-line-result-text-file-with-awk-bash-or-r

にあった。AWK スクリプトを平易に書き変えた。


★ 以下のような定式化された入力ファイル melting.txt 

  The MELTING results are :

 Enthalpy : -181,100 cal/mol ( -756,998 J /mol)

 Entropy : -467.3 cal/mol-K ( -1,953.31 J /mol-K)

 Melting temperature : 75.13 degrees C.


  The MELTING results are :

 Enthalpy : -170,800 cal/mol ( -713,944 J /mol)

 Entropy : -444 cal/mol-K ( -1,855.92 J /mol-K)

 Melting temperature : 70.6 degrees C.

からデータを取り出し,R で

  Enthalpy Entropy MeltingTemperature
1  -181100  -467.3              75.13
2  -170800  -444.0              70.60

のようなデータフレームを作る。

★ 用意する AWK スクリプト melting.awk

/Enthalpy/ || /Entropy/ { # "Enthalpy" または "Entropy" を含む行について
    n = split($0, a, " ") # 空白でフィールドに区切る
    gsub(",", "", a[3])   # a[3] が求めるデータである。数値区切りの「,」を消去する
    printf "%g, ", a[3]   # 書き出す
}
/Melting temperature/ {   # "Melting temperature" を含む行について
    n = split($0, a, " ") # 空白でフィールドに区切る
    print a[4]            # 求めるデータ a[4] を書き出す
}

★ R コンソールで以下を実行する。

CSV ファイルに結果を書き出す。
以下で |> を使っているが,tidyverse ではなく Base R のパイプである。
最初の文字列がコンソールで入力されるコマンドである。(脚注参照)

"awk -f melting.awk melting.txt" |>
    pipe() |>
    readLines() |>
    write("results.csv")

後は,ありふれた処理。CSV ファイルをデータフレームに読み込むだけである。

df = read.csv("results.csv", header=FALSE,
         col.names=c("Enthalpy", "Entropy", "MeltingTemperature"))

出来上がり。

  Enthalpy Entropy MeltingTemperature
1  -181100  -467.3              75.13
2  -170800  -444.0              70.60

なお,入力ファイルがちゃんと同じフォーマットであることを仮定している。
その仮定ができない場合の処理を AWK スクリプトに含めるかどうかは,程度問題。

==========
脚注

以下の一行をコンソールで入力すれば

$ > awk -f melting.awk melting.txt 

以下が表示される

-181100, -467.3, 75.13
-170800, -444, 70.6

結果をファイルに入れるには出力を results.csv へリダイレクトすればよい。

$ > awk -f melting.awk melting.txt > results.csv

=================

なお,R だけでやろうとすると以下のようにもなるだろうか。

txt = readLines("melting.txt")
df = NULL
x = NULL
for (i in 1:length(txt)) {
	if (grepl("Enthalpy", txt[i]) || grepl("Entropy", txt[i])) {
		target = sub(",", "", unlist(strsplit(txt[i], " "))[4])
		x = append(x, target)
	} else if (grepl("Melting temperature", txt[i])) {
		x = append(x, unlist(strsplit(txt[i], " "))[5])
		df = rbind(df, x)
		x = NULL
	}
}
df = as.data.frame(df, col.names=c("Enthalpy", "Entropy", "MeltingTemperature"))
print(df)

Julia でやろうとすると以下のようになる(書式に関して別の仮定を置く)

using DataFrames
txt = readlines("melting.txt")
x = Float64[]
for s in txt
    pos = findfirst(r"[-+]?[0-9,]+\.?[0-9]*", s)
    isnothing(pos) == false && append!(x, parse(Float64, replace(s[pos], "," => "")))
end
df = DataFrame(Matrix(reshape(x, 3, :)'), ["Enthalpy", "Entropy", "MeltingTemperature"])
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

AWK で製表

2022年09月07日 | ブログラミング

以下のような入力ファイル CodeFormat

Code
Format
Example
0
dd-mmm-yyyy HH:MM:SS
07-Sep-2000 15:38:09
1
dd-mmm-yyyy
07-Sep-2000
2
mm/dd/yy
09/07/00
3
mmm
Sep
4
m
S

からデータを読み込み

Code | Format | Example
:--|:--|:--
0 | dd-mmm-yyyy HH:MM:SS | 07-Sep-2000 15:38:09
1 | dd-mmm-yyyy | 07-Sep-2000
2 | mm/dd/yy | 09/07/00
3 | mmm | Sep
4 | m | S

のように整形して出力ファイル table に書き込む。

つまり,最終形の表は3列からなり,各列は | で区切られている。元のデータは3行で表の1行になる。

awk で書くとこんなスクリプト

{
	getline a
	getline b
	printf "%s | %s | %s\n", $0, a, b
}
FNR == 3 {
	print ":--|:--|:--"
}

こんなふうに実行する。

awk -f temp.awk < CodeFormat >table

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

RStudio で awk を使う

2022年09月03日 | ブログラミング

前の記事で ```{awk} ... ``` が動かないと書いた。

https://gedevan-aleksizde.github.io/rmarkdown-cookbook/custom-engine.html

の「15.1 カスタム言語エンジンを登録する」を読んで,以下のように解決した(のかな?)。

最初に一回だけ,以下の R スクリプトを実行する。

knitr::knit_engines$set(awk = function(options) {
  code <- paste(options$code, collapse = '\n')
  out  <- system2('awk', shQuote(code), stdout = TRUE)
  knitr::engine_output(options, code, out)
})

この後,awk によるチャンクを書く。

```{awk}
BEGIN {
    for(i = 1; i <= 10; i++) {
        print i, sqrt(i)
    }
}
```

実行すると,以下の結果を得る。

## 1 1
## 2 1.41421
## 3 1.73205
## 4 2
## 5 2.23607
## 6 2.44949
## 7 2.64575
## 8 2.82843
## 9 3
## 10 3.16228

```{awk}
BEGIN {print "Hello, world!"}
```
## Hello, world!
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

【数学のひっかけ問題】三角形の面積を求めよ

2022年08月30日 | ブログラミング

【数学のひっかけ問題】三角形の面積を求めよ
https://nazesuugaku.com/fake_triangle/
で,「底辺が10cm、高さ6cmの直角三角形の面積を求めなさい。」

に対して,「そのような直角三角形は存在しない」とある。

確かに記事中のように底辺をとると「そのような直角三角形は存在しない」であるが,明らかに別の直角三角形もあるじゃないか?

短い問題文の中に,この三角形を排除する記述はないと思うのだが。

元々は「マイクロソフトの入社試験」だそうなので,原文を見ないとどうとも言えないが。

どうも,ご丁寧に図が描いてあったらしい。これじゃ「そんな三角形は存在しない」わなぁ。

真面目な解答もありました。(すごいなあ)

これ解けますか?(後編:マイクロソフトの三角形ありました)
https://blog.tech-monex.com/entry/2021/08/06/130000

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

簡単なデータ前処理で速度比較 tidyr, BaseR, AWK -- その3

2022年08月29日 | ブログラミング

sample.csv は 17035201 行の CSV ファイルである。最初の 7 行は以下のようになっている。

"id","label"
1,"aaa_あああ"
2,"aaa_いいい"
3,"bbb_ううう"
4,"bbb_えええ"
5,"ccc_おおお"
6,"ccc_かかか"

これを入力とし,以下のように変更を加え出力する。

"id",label"
1,"aaa"
1,"あああ"
2,"aaa"
2,"いいい"
3,"bbb"
3,"ううう"
4,"bbb"
4,"えええ"
5,"ccc"
5,"おおお"
6,"ccc"
6,"かかか"

# tidyr

あまり 'tidy' なプログラムでもないが,この 3 行のプログラムでの実行時間は 125.581, 122.979, 121.734 であった。
平均値は 123.431 秒。

しかし,システムが使用する時間が同程度あり,結局経過時間(計算開始から結果が出るまでの時間)は実に388.996, 283.905, 297.495 で,平均値は 323.465 秒,実に 5 分超である。

library(dplyr)
library(tidyr)

system.time({
    sample = read.csv("sample.csv")
    sample_row <- sample %>% separate_rows(label,sep="_")
    write.csv(sample_row, "tidyr.csv", row.names=FALSE)
})

# Base R

最近では tidyr は知っているが,Base R は知らない(書けない)という人も多いようであるが,この 4 行のプログラムでの実行時間は 25.035, 25.480, 25.446 であった。
平均値は 25.320 秒。

経過時間は 24.190 秒である。tidyr によるものより 30 倍速い。

system.time({
    sample = read.csv("sample.csv")
    a = unlist(strsplit(sample$label, "_"))
    sample = data.frame(id=rep(sample$id, each=2), label=a)
    write.csv(sample, "BaseR.csv", row.names=FALSE)
})

# AWK

AWK を知らない人も多いと思うが,この例のような簡単なデータ前処理には十分使える。
この CSV ファイルの構造をフルに利用して,実質 5 行のプログラムを書く。実行時間は 21.380, 22.024, 21.848 であった。
平均値は 21.751 秒。

BaseR によるよりも 16% 速い。tidyr に比べると 5 倍速い。

BEGIN {
    FS = ","
    getline
    print $0
}
{
    split($2, t, "_")
    printf "%s,%s\"\n%s,\"%s\n", $1, t[1], $1, t[2]
}

結果

またまた,AWK が最速という結果になった。

R はデータをすべてメモリ中に保存している。しかも,場合によってはそのコピーを作ったりすることもある。このプログラムが動いているとき R は 2GB ものメモリを消費している。

AWK はデータを「一行読んで,処理して,書き出して」を繰り返すのでメモリは殆ど使わない。

そのあたりがこういう結果になっているのであろう。

特に tidyr は,BaseR に比べてメモリ操作が下手くそ(余計なことをしている)なのであろう。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

簡単なデータ前処理で速度比較 tidyr, BaseR, AWK -- その2

2022年08月28日 | ブログラミング

sample.csv は 17035201 行の CSV ファイルである。最初の 7 行は以下のようになっている。

"id","label"
1,"aaa_あああ"
2,"aaa_いいい"
3,"bbb_ううう"
4,"bbb_えええ"
5,"ccc_おおお"
6,"ccc_かかか"

これを入力とし,以下のように変更を加え出力する。

"id","new_label1","new_label2"
1,"aaa","あああ"
2,"aaa","いいい"
3,"bbb","ううう"
4,"bbb","えええ"
5,"ccc","おおお"
6,"ccc","かかか"

# tidyr

あまり 'tidy' なプログラムでもないが,この 3 行のプログラムでの実行時間は 111.195, 101.132, 100.276 であった。
平均値は 104.201 秒。

しかし,システムが使用する時間が同程度あり,結局経過時間(計算開始から結果が出るまでの時間)は実に751.059, 686.955, 827.347 で,平均値は 755.120 秒,実に 12 分超である。

library(dplyr)
library(tidyr)

system.time({
    sample = read.csv("sample.csv")
    sample_col <- sample %>% separate(label,into=c("new_label1","new_label2"),sep="_")
    write.csv(sample_col, "tidyr.csv", row.names=FALSE)
})

# Base R

最近では tidyr は知っているが,Base R は知らない(書けない)という人も多いようであるが,この 6 行のプログラムでの実行時間は 23.509, 23.268, 22.892 であった。平均値は 23.223 秒。


経過時間は 24.190 秒である。tidyr によるものより 30 倍速い。

system.time({
    sample = read.csv("sample.csv")
    a = unlist(strsplit(sample$label, "_"))
    sample$new_label1 = a[seq(1, 12, by=2)]
    sample$new_label2 = a[seq(2, 12, by=2)]
    sample = sample[c("id","new_label1","new_label2")]
    write.csv(sample, "BaseR.csv", row.names=FALSE)
})

# AWK

AWK を知らない人も多いと思うが,この例のような簡単なデータ前処理には十分使える。
この CSV ファイルの構造をフルに利用して,実質 5 行のプログラムを書く。実行時間は 20.328, 20.503, 20.126 であった。

平均値は 20.319 秒。

BaseR によるよりも二割方速い。tidyr に比べると 5 倍速い。

BEGIN {
    FS = ","
    getline
    print "\"id\",\"new_label1\",\"new_label2\""
}
{
    split($2, t, "_")
    printf "%s,%s\",\"%s\n", $1, t[1], t[2]
}

結果

AWK が最速という結果になった。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

簡単なデータ前処理で速度比較 tidyr, BaseR, AWK

2022年08月27日 | ブログラミング

sample.csv は 17035201 行の CSV ファイルである。最初の 7 行は以下のようになっている。

"id","label","label2"
1,"aaa","あああ"
2,"aaa","いいい"
3,"bbb","ううう"
4,"bbb","えええ"
5,"ccc","おおお"
6,"ccc","かかか"

これを入力とし,以下のように変更を加え出力する。

"id","new_label"
1,"aaa_あああ"
2,"aaa_いいい"
3,"bbb_ううう"
4,"bbb_えええ"
5,"ccc_おおお"
6,"ccc_かかか"

# tidyr

あまり 'tidy' なプログラムでもないが,この 3 行のプログラムでの実行時間は 11.633, 11.909, 12.028 であった。
平均値は 11.857 秒。

library(dplyr)
library(tidyr)

system.time({
    sample = read.csv("sample.csv")
    sample_col <- sample %>% unite(new_label,label,label2,remove=TRUE,sep="_")
    write.csv(sample_col, "tidyr.csv", row.names=FALSE)
})

# Base R

最近では tidyr は知っているが,Base R は知らない(書けない)という人も多いようであるが,この 4 行のプログラムでの実行時間は 12.017, 11.987, 12.020 であった。
平均値は 12.008 秒。

system.time({
    sample = read.csv("sample.csv")
    sample$new_label = paste(sample$label, sample$label2, sep="_")
    sample = sample[c("id", "new_label")]
    write.csv(sample, "BaseR.csv", row.names=FALSE)
})

# AWK

AWK を知らない人も多いと思うが,この例のような簡単なデータ前処理には十分使える。
この CSV ファイルの構造をフルに利用して,実質 4 行のプログラムを書く。
これくらい短ければ,使い捨てのプログラムをすぐ書ける。
実行時間は 11.026, 11.087, 10.952 であった。
平均値は 11.0217 秒。

BEGIN {
    getline
    print "\"id\",\"new_label\""
}

{
    sub("\",\"", "_", $0)
    print $0
}

結果

AWK が最速という結果になった。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

階乗競争

2022年08月17日 | ブログラミング

階乗の限界と計算速度を Python, Julia, R, Octave で比較してみた

追記: 2022/08/18  R での結果を更新。x86-64 版でやったら早々にクラッシュしていた。M1 チップ対応版で Julia と同等以上の速度である。

# Python 3.10.6

from math import factorial
from time import time
s = time()
a = factorial(100000)
print(time() - s)

    0.1885082721710205 sec.

# Julia 1.7.3

@time a = factorial(big(100000));

      0.011688 seconds (302 allocations: 3.076 MiB)


# R 4.2.1 (M1)

library(gmp)
> system.time({a = factorialZ(100000)})
             ユーザ             システム                 経過  
0.009999999999999787 0.000000000000000000 0.009999999999990905 


# Octave 6.2.0

tic
a = factorial(18); # 整数値解を表示するにはこれが限界
toc

    Elapsed time is 0.00777102 seconds.

ということで,Julia と R の圧勝...かな?

Julia も R も,gmp を使っているので,Python も gmpy を使えば同じ速度になるのかも知れない。が,現在の環境では pip install gmpy はできるのだが,いざ import gmpy すると,エラーになるので,確認できない。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ヒルベルト行列--2

2022年08月15日 | ブログラミング

ヒルベルト行列

ヒルベルト行列とその逆行列を求め,両者の行列乗算で単位行列になることを,4 種の言語でやってみた。

Octave と Julia はさすが。
R はちょっと誤差が大きい?
Python は R より誤差が大きい?

Octave

hilb
Return the Hilbert matrix of order N.

invhilb
Return the inverse of the Hilbert matrix of order N.

hilb(5)

    ans =
    
       1.0000   0.5000   0.3333   0.2500   0.2000
       0.5000   0.3333   0.2500   0.2000   0.1667
       0.3333   0.2500   0.2000   0.1667   0.1429
       0.2500   0.2000   0.1667   0.1429   0.1250
       0.2000   0.1667   0.1429   0.1250   0.1111

invhilb(5)

    ans =
    
           25     -300     1050    -1400      630
         -300     4800   -18900    26880   -12600
         1050   -18900    79380  -117600    56700
        -1400    26880  -117600   179200   -88200
          630   -12600    56700   -88200    44100

hilb(5) * invhilb(5)

    ans =
    
       1.0000        0        0        0        0
            0   1.0000        0        0        0
            0        0   1.0000  -0.0000        0
            0        0        0   1.0000        0
            0        0        0        0   1.0000
    


Julia

# import Pkg; Pkg.add("Nemo")
using Nemo
M = MatrixSpace(QQ, 5, 5)
h = hilbert(M)
    
    Welcome to Nemo version 0.32.2
    
    Nemo comes with absolutely no warranty whatsoever

    [   1   1//2   1//3   1//4   1//5]
    [1//2   1//3   1//4   1//5   1//6]
    [1//3   1//4   1//5   1//6   1//7]
    [1//4   1//5   1//6   1//7   1//8]
    [1//5   1//6   1//7   1//8   1//9]


inv(h)

    [   25     -300      1050     -1400      630]
    [ -300     4800    -18900     26880   -12600]
    [ 1050   -18900     79380   -117600    56700]
    [-1400    26880   -117600    179200   -88200]
    [  630   -12600     56700    -88200    44100]


h * inv(h)

    [1   0   0   0   0]
    [0   1   0   0   0]
    [0   0   1   0   0]
    [0   0   0   1   0]
    [0   0   0   0   1]

R


# install.packages("matrixcalc")
library(matrixcalc)

h = hilbert.matrix(5)
h

A matrix: 5 × 5 of type dbl
1.0000000 0.5000000 0.3333333 0.2500000 0.2000000
0.5000000 0.3333333 0.2500000 0.2000000 0.1666667
0.3333333 0.2500000 0.2000000 0.1666667 0.1428571
0.2500000 0.2000000 0.1666667 0.1428571 0.1250000
0.2000000 0.1666667 0.1428571 0.1250000 0.1111111

solve(h)

A matrix: 5 × 5 of type dbl
   25   -300    1050   -1400    630
 -300   4800  -18900   26880 -12600
 1050 -18900   79380 -117600  56700
-1400  26880 -117600  179200 -88200
  630 -12600   56700  -88200  44100

h %*% solve(h)

A matrix: 5 × 5 of type dbl
 1.000000e+00 -4.547474e-13 -1.818989e-12  0.000000e+00  0.000000e+00
-1.421085e-14  1.000000e+00  0.000000e+00 -5.456968e-12 -2.728484e-12
 0.000000e+00 -4.547474e-13  1.000000e+00  0.000000e+00 -9.094947e-13
 0.000000e+00  2.273737e-13  0.000000e+00  1.000000e+00 -9.094947e-13
 1.421085e-14 -2.273737e-13  0.000000e+00 -1.818989e-12  1.000000e+00

round(h %*% solve(h), 10)

A matrix: 5 × 5 of type dbl
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1

Python

from scipy.linalg import hilbert, invhilbert
hilbert(5)


    array([[1.        , 0.5       , 0.33333333, 0.25      , 0.2       ],
           [0.5       , 0.33333333, 0.25      , 0.2       , 0.16666667],
           [0.33333333, 0.25      , 0.2       , 0.16666667, 0.14285714],
           [0.25      , 0.2       , 0.16666667, 0.14285714, 0.125     ],
           [0.2       , 0.16666667, 0.14285714, 0.125     , 0.11111111]])

invhilbert(5)

    array([[ 2.500e+01, -3.000e+02,  1.050e+03, -1.400e+03,  6.300e+02],
           [-3.000e+02,  4.800e+03, -1.890e+04,  2.688e+04, -1.260e+04],
           [ 1.050e+03, -1.890e+04,  7.938e+04, -1.176e+05,  5.670e+04],
           [-1.400e+03,  2.688e+04, -1.176e+05,  1.792e+05, -8.820e+04],
           [ 6.300e+02, -1.260e+04,  5.670e+04, -8.820e+04,  4.410e+04]])

hilbert(5) @ invhilbert(5)

    array([[ 1.00000000e+00, -1.39888101e-13,  6.29496455e-13,  2.65876210e-12, -1.32938105e-12],
           [-2.00395256e-14,  1.00000000e+00, -2.34356978e-12,  2.63500333e-12, -1.31750166e-12],
           [ 2.34257058e-14, -1.27453603e-13,  1.00000000e+00, -2.93853830e-12,  5.59774449e-13],
           [ 0.00000000e+00, -2.27373675e-13,  9.09494702e-13,  1.00000000e+00,  0.00000000e+00],
           [-1.80966353e-14,  3.05089287e-13, -3.49720253e-13,  2.36299869e-12,  1.00000000e+00]])

import numpy as np
np.round(hilbert(5) @ invhilbert(5), 10)

    array([[ 1., -0.,  0.,  0., -0.],
           [-0.,  1., -0.,  0., -0.],
           [ 0., -0.,  1., -0.,  0.],
           [ 0., -0.,  0.,  1.,  0.],
           [-0.,  0., -0.,  0.,  1.]])

 

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

早期リターンではなくなっているぞ

2022年08月14日 | ブログラミング

以下の例を上げてきたが,これはもはや「早期リターンではない」

class Student:

  def __init__(self, student_id, name):
    self.student_id = student_id
    self.name = name

  def student_check(self):
    
    if self.student_id != "" or self.name != "":
      if len(self.student_id) > 12:
        flg = False
      else:
        flg = True
    else:
      flg = False
    return flg

student_exe = Student("101122222212","山田花子")
student_exe.student_check()

if のネストを避ける」というなら,以下のようにすればよい。これで「早期リターン」だ!!

  def student_check(self):
    
    if self.student_id != "" or self.name != "":
      return len(self.student_id) <= 12
    else:
      return False

蛇足だが,flg なんて変数名はダメダメ。flag にしよう。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

早期リターンとガード節

2022年08月14日 | ブログラミング

早期リターンとガード節

ガード節を使わないプログラムとして挙げられているのが prog1

if value === "hoge"
  result = "hoge"
else
  if value === "fuga"
    result = "fuga"
  else
    if value === "hogefuga"
      result = "hogefuga"
end

return result

ガード節を使うプログラムとして挙げられているのが prog2

if value === "hoge"
  return "hoge"
end

if value === "huga"
  return "fuga"
end

return "hogefuga"

この言語は何かわからないが,やっていることはわかる。

疑問は,「この言語は if-else しかないのか?if-elseif-else はないのか?」ということ

prog2 は,以下のように書くとわかりやすいのではないか? prog3

if value === "hoge"
  return "hoge"
else if value === "huga"
  return "fuga"
else
  return "hogefuga"
end

prog1 では,value が "hoge", "huga", "hogefuga" 以外の場合,未定義の result を返そうとする。言語によっては単に何も返さないと解釈されることもあるが,いずれにせよ,論理エラーである。

prog2, prog3  では,value が "hoge", "huga" 以外の場合,無条件に "hogefuga" を返す。これは論理エラーである。

prog3 はもう一段 else if があるべきだ。 prog4

これは prog1 を else if を使って,更に条件のチェック漏れを補完したプログラムだ。

if value === "hoge"
  return "hoge"
else if value === "huga"
  return "fuga"
else if value === "hogefuga"
  return "hogefuga"
else
  return "ERROR!!"
end

最後に,このバカバカしいプログラムに限ってだが,以下のように書くのがベストだ。prog5

if value === "hoge" || value === "huga" || value === "hogefuga"
  return value
else
  return "ERROR!!"
end

あるプログラミングスタイルを推奨する記事を書くとき,悪い例と良い例を提示するが,提示されたプログラムがクソだと,プログラミングスタイル自体がクソに見える。

早期リターンは必要なら使えばよい。

いずれにしても,プログラムをよく解析して,最良なアルゴリズムを適用することだ。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

ヒルベルト行列

2022年08月14日 | ブログラミング

Julia で書くと以下のようになる。

一行で書けるが決してこの書き方をすすめるわけではない。普通に2重ループで書くほうがよい。

演算子に // を使ったのは,分数型で答えを出力するためである。

julia> h(n) = [1 // (i + j - 1) for i in 1:n, j in 1:n]

h (generic function with 1 method)

julia> h(5)

5×5 Matrix{Rational{Int64}}:

 1//1  1//2  1//3  1//4  1//5

 1//2  1//3  1//4  1//5  1//6

 1//3  1//4  1//5  1//6  1//7

 1//4  1//5  1//6  1//7  1//8

 1//5  1//6  1//7  1//8  1//9

実数型に変換すると。

julia> float.(h(5))

5×5 Matrix{Float64}:

 1.0       0.5       0.333333  0.25      0.2

 0.5       0.333333  0.25      0.2       0.166667

 0.333333  0.25      0.2       0.166667  0.142857

 0.25      0.2       0.166667  0.142857  0.125

 0.2       0.166667  0.142857  0.125     0.111111

Python だと

>>> a = [[1/(i+j-1) for i in range(1, n+1)] for j in range(1, n+1)]

のようになるが,range(1, n+1) が鬱陶しい。

>>> a = [[1/(i+j+1) for i in range(n)] for j in range(n)]

とすればよい。

しかし,n = 5000 のとき,Julia で // を / にして直接実数型の結果を返す場合に比べて,Python は,ほぼ 24 倍遅い

追記:

Nemo パッケージに hilbert 関数があった。

 

julia> using Nemo

julia> M = MatrixSpace(QQ, 5, 5)

Matrix Space of 5 rows and 5 columns over Rational Field

 

julia> h = hilbert(M)

[   1   1//2   1//3   1//4   1//5]

[1//2   1//3   1//4   1//5   1//6]

[1//3   1//4   1//5   1//6   1//7]

[1//4   1//5   1//6   1//7   1//8]

[1//5   1//6   1//7   1//8   1//9]

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村