裏 RjpWiki

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

Python なんかやめて Julia にしよう!!!!!

2020年12月27日 | ブログラミング

macOS Big SurでPythonをはじめてみる

という記事があったのだけど

  • Pythonのバージョン2系とバージョン3系の解説があること
  • バージョン3へのアップグレードについて記述があること
  • プログラム経験はあるけど、Pythonは初心者という人向けであること

とはいっているものの,不安だなあ。

Mac OS は,いまだに Python 2 を推奨しているということか?

推奨していなくても,受け取る側は「推奨されている」とオモウワナア!

大丈夫か?

もうねえ,Python 3.9 にすべき,というか。

もう,初めからやるなら,Julia がお勧め。

もうねえ,いまどき,Python やってる場合じゃない,と,思いますよ。

一歩先を行きませんか????

みんなと同じことやってる場合じゃない。

 

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

groupby で,自作の関数を適用する(Python)

2020年12月27日 | Python

df2 = df.groupby(群)

df2.agg(自作関数の名前)

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

素数列挙プログラムのスピードアップ

2020年12月27日 | ブログラミング

以下のようなプログラムがあった。

このプログラムだと,10**8 以下の素数を探索するのに 18 日くらいかかる。

import time

primes_list = []
upper_lim   = 10**3
start_time  = time.time()

for integer in range(2, upper_lim + 1, 1):
    if len(primes_list) < 1 :
        primes_list.append(integer)
    else:
        is_divisible = False
        for prime in primes_list:
            if integer % prime == 0:
                is_divisible = True
                break
        if not is_divisible:
            primes_list.append(integer)

#print(primes_list)
print(len(primes_list), "prime numbers foud.")

elapsed_time = time.time() - start_time # 経過時間 = 現在時刻 - 開始時刻
print ("run time: {0}".format(elapsed_time) + " seconds")

偶数の素数は 2 だけ。それ以外は奇数。range(2, upper_lim + 1, 1) でぶん回すのは少なくとも2倍の時間が掛かる。

for ループの中に len(primes_list) < 1 を毎回判定する if ブロックは無駄。

is_divisible という変数を使っているが,後で not is_divisible として使っているのなら,is_prime という変数を作ったほうがわかりやすい。

ある数が,primes_list の中にある素数で割りきれるか primes_list の全体を走査しているが,その数の平方根以下の要素まで調べればよい。そこまでで割り切れなければ素数。

Python の癖であるが,関数にしたほうが速い。

++++++++++

他の人からアドバイスがあって,書き直されたプログラムが3とおりあった。

関数化したこと
2 を特別に扱い,range(3, upper_limit + 1, 2) で探索すること。
all(integer % prime != 0 for prime in primes_list) を使うこと。
しかし,これはあまりよい提案ではないことがわかる。
素数かどうかの走査を早めに終えるためにはこの方法はよくない。

def primes_up_to_(upper_limit):
    if upper_limit < 2:
        return []
    primes_list = [2]
    for integer in range(3, upper_limit + 1, 2):
        if all(integer % prime != 0 for prime in primes_list):
            primes_list.append(integer)
    return primes_list

++++++++++

もう一つのバージョン

for integer in range(2, upper_lim + 1, 1):
    if len(primes_list) < 1 :
        primes_list.append(integer)
    else:
        is_divisible = False
        for prime in primes_list:
            # if prime >= math.sqrt(integer): # このやり方は実によい!!
            if prime > math.sqrt(integer): # 但し,> でないと間違い
                break
            elif integer % prime == 0:
                is_divisible = True
                break
        if not is_divisible:
            primes_list.append(integer)

++++++++++

もう一つのバージョンだが,何をやっているか理解しておらず,処理の重複のため長時間かかることになってしまった。

追加したものは if all() と重複する余分なもの。百害あって一利なし。それに,前のバージョンの prime > math.sqrt(integer) がなくなってしまった。

def primes_up_to_3(upper_limit): # 関数化
    if upper_limit < 2:
        return []
    primes_list = [2]
    for integer in range(3, upper_limit + 1, 2):
        temp_primes_list = []                                       # 追加
        for prime in primes_list:                                   # 追加
            if prime <= math.sqrt(integer):                         # 追加
                temp_primes_list.append(prime)                      # 追加
        if all(integer % prime != 0 for prime in temp_primes_list):
            primes_list.append(integer)
    return primes_list

++++++++++

私が考えていたバージョン。

def gen_primes2(upper_lim = 10000):
    primes_list = [2]
    for integer in range(3, upper_lim + 1, 2):
        is_prime = True
        upper_lim_sqrt = int(integer**0.5)
        for prime in primes_list:
            if prime > upper_lim_sqrt: # 時短にかなり有効
                break
            elif integer % prime == 0:
                is_prime = False
                break
        if is_prime:
            primes_list.append(integer)
    return primes_list

これだと,最初のバージョンでは 10**8 までの検索に 18 日かかっていたであろうものが,10 分で終わる。

++++++++++

しかし,以下の Julia で書いたプログラムだと,さらにその 10 倍速い。

function gen_primes2(upper_lim = 10000)
    primes_list = [2]
    for integer = 3:2:upper_lim
        upper_lim_sqrt = ceil(sqrt(integer))
        is_prime = true
        for prime in primes_list
            if prime >  upper_lim_sqrt
                break
            elseif integer % prime == 0
                is_prime = false
                break
            end
        end
        if is_prime
            append!(primes_list, integer)
        end
    end
    println("$(length(primes_list)) prime numbers foud.")
    # println(primes_list)
end

@time gen_primes2(10^8)
# $ julia gen_primes2.jl
# 5761455 prime numbers foud.
# 54.732656 seconds (35 allocations: 65.001 MiB, 0.00% gc time)

10**8 までの検索が 1分で終わる。

つまり,元のプログラムの2万6千倍速いのだ。

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

Julia のプログラムを書いてみよう -- 1

2020年12月27日 | ブログラミング

The Julia Language を読み進めているが,1300ページもあるので,モチベーションを維持するために,実際にプログラムも書いてみなくては。

julia> #=
       他の言語と違うところに注目してまとめてみよう。
       複数行の注釈は #= ... =#
       形式としては Java などの /* ... */
       =#

julia> println("我が輩は猫である。\n名前は", "まだない。")
我が輩は猫である。
名前はまだない。

文字列はダブルクオート '"' でなければならない。シングルクオート "'" だとエラーになる。
出力後改行するには print() ではなく println() を使う。これも Java などと同じ。print() で行末に '\n' を付けてもいいけど。
Python の print() とは違い,出力項目の間に自動的に空白は入らない。

julia> print('A', '1', 'π', '\n')
A1π

シングルクオートでくくるのは文字である。'\n' も改行を表す 1 文字。
'π' などのギリシア文字,特殊文字は '\pi[tab]' で入力できる( [tab]はタブキーを押す)。

julia> println("2^5 = $(2^5)")
2^5 = 32

羃乗は '^'。Python が '**' なのは,ちょっと異端なのだ。
"2^5 = $(2^5)" は 文字列中に式の結果を展開する記法。Python の print(f"2^5 = {2^5}") に相当する。 

julia> println("整数除算: div(21, 4) = $(div(21, 4)) または 21 ÷ 4 = $(21 ÷ 4)\n",
       "  ÷ は \\div で入力する。\n",
       "  // は 分数形式(有理数)になる。Python と違うので要注意。\n",
       "  21 // 4 = $(21 // 4), float(21 // 4) = $(float(21 // 4))\n",
       "  240 // 36 = $(240 // 36)")
整数除算: div(21, 4) = 5 または 21 ÷ 4 = 5
  ÷ は \div で入力する。
  // は 分数形式(有理数)になる。Python と違うので要注意。
  21 // 4 = 21//4, float(21 // 4) = 5.25
  240 // 36 = 20//3

整数剰余: mod(21, 4) = 1 または rem(21, 4) = 1 または 21 % 4 = 1
 しかし,除数,被除数に符号が付くと,ややこしいことになる。

整数 a, b に対する除算の結果の「商」と「余り」について「商*b + 剰余 = a」という等式が成り立つことが規定されている。

3 つの関数を定義して,この等式が成り立つかどうかをチェックしてみよう。結果の表示は 「a, b, 商,剰余,等式が成り立つかどうか」の順である。

julia> h(a, b) = println("div() and mod(): $a, $b, $(div(a, b)), $(mod(a, b)), $(div(a, b) * b + mod(a, b) == a)");

julia> g(a, b) = println("div() and rem(): $a, $b, $(div(a, b)), $(rem(a, b)), $(div(a, b) * b + rem(a, b) == a)");

julia> f(a, b) = println("div() and %: $a, $b, $(div(a, b)), $(a % b), $(div(a, b) * b + a % b == a)");

julia> a =  21; b =  4; h(a, b); g(a, b); f(a, b);
div() and mod(): 21, 4, 5, 1, true
div() and rem(): 21, 4, 5, 1, true
div() and %: 21, 4, 5, 1, true

julia> a =  21; b = -4; h(a, b); g(a, b); f(a, b);
div() and mod(): 21, -4, -5, -3, false
div() and rem(): 21, -4, -5, 1, true
div() and %: 21, -4, -5, 1, true

julia> a = -21; b =  4; h(a, b); g(a, b); f(a, b);
div() and mod(): -21, 4, -5, 3, false
div() and rem(): -21, 4, -5, -1, true
div() and %: -21, 4, -5, -1, true

julia> a = -21; b = -4; h(a, b); g(a, b); f(a, b);
div() and mod(): -21, -4, 5, -1, true
div() and rem(): -21, -4, 5, -1, true
div() and %: -21, -4, 5, -1, true

結果は

除数,被除数の符号が同じときには,除数の計算に mod(),rem(), % のどれを使っても,等式は成り立つ。
除数,被除数の符号が違うときには,除数の計算に rem(), % のいずれを使っても,等式は成り立つが,mod() を使った場合は等式は成り立たない。

mod() は % とは違うということである。

ううん。こんなことばかりしているから,学習が進まない。

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

整数除算の商と剰余

2020年12月27日 | ブログラミング

整数同士の割り算の,商と剰余についてまとめておく。

私が今まで使ったことのある言語についてのみであるが。
Prorog とか Pascal とか PL/I とかそのほかにもあるが,今となっては実行環境がないので,確かめることができない。

結果を先に述べておく。

2 つの整数を (a, b) とすると,それぞれの符号で 4 通りある。例として,(21, 4), (21, -4), (-21, 4), (-21, -4) でやってみる。

★★★  (商, 剰余) がそれぞれ (5, 1), (-5, 1), (-5, -1), (5, -1) となる言語

AWK, C, C#, C++, COBOL, D, F#, FORTRAN, Go, Java, JavaScript, PHP, Scala, Swift, VB
Haskel で quot() と rem() を使う場合,
Julia で div() と rem() を使う場合,
Perl でゼロ方向への丸めをするようにプログラムする場合

★★  (商, 剰余) がそれぞれ (5, 1), (-6, -3), (-6, 3), (5, -1) となる言語

Python2, Python3, R, Ruby,
Haskel で dif() と mod() を使う場合,
Julia で剰余の計算を a - div(a, b) * b で計算するようにプログラムする場合,
Perl で -∞ 方向への丸めを行い,剰余の計算を a - div(a, b) * b で計算するようにプログラムする場合

★ 迂闊にやると,(商, 剰余) がそれぞれ (5, 1), (-5, -3), (-5, 3), (5, -1) となる言語

Julia で div() と mod() を使う場合(誤った選択。div() と rem() を使えば ★★★,剰余の計算を自分ですれば ★★)
Perl で int($a / $b), と $a % $b を使う場合(適切にプログラムして ★★★ にするか ★★ にする)
このような場合,「 a = 商 * b + 剰余」が成り立たないので,不適切な解となってしまう。

========= AWK

BEGIN {
    OFS = ", "
    a = 21
    b = 4
    print int(a / b), a % b
}

========= C

#include
#include

int main(int argc, char **argv) {
    int a = 21;
    int b = 4;
    printf("%d, %d\n", a / b, a % b);
    return EXIT_SUCCESS;
}

========= C#

public class Hello{
    public static void Main(){
        int a, b;
        a = 21;
        b = 4;
        System.Console.WriteLine(a / b + ", " + a % b);
    }
}

========= C++

#include

int main(int argc, char **argv) {
    int a = 21;
    int b = 4;
    std::cout <
    return EXIT_SUCCESS;
}

========= COBOL

identification division.
program-id. Hello.
data division.
working-storage section.
01 working-area.
    02 x pic s9.
    02 y pic s9.
procedure division.
divide 21 by 4 giving x remainder y.
display x, ",  ", y.

========= D

import std.stdio;
void main() {
    int a, b;
    a = 21;
    b = 4;
    writeln(a / b, ", ", a % b);
}

========= F#

let a = 21;;
let b = 4;;
printfn "%d, %d" (a / b) (a % b);;

========= Fortran

program main
 implicit none
 integer a, b
 a = -21
 b = -4
 write(*, *) int(a / b), ", ", mod(a, b)
end program main

========= Go

package main
import "fmt"
func main() {
    var a int = 21
    var b int = 4
    fmt.Printf("%d, %d", a / b, a % b)
}

========= Java

import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        int a = 21;
        int b = 4;
        System.out.println(a / b + ", " + a % b);
    }
}

========= JavaScript

var a = 21;
var b = 4;
var x = a / b;
// 一律に Math.floor を紹介するページが多いが,a, b の符号が違うときには誤った答えになるので注意
x = x < 0 ? Math.ceil(x) : Math.floor(x)
console.log(x + ", " + a % b);

========= PHP

$a = 21;
$b = 4;
echo (int)($a / $b), ", ", $a % $b;
?>

========= Scala

object Main extends App {
    var a = 21
    var b = 4
    println(a / b + ", " + a % b)
}

========= Swift

var a:Int = -23
var b:Int = 4
print("\(a / b), \(a % b)")

========= VB VisualBasic

public class compiler
  shared function Main as integer
    Dim a As Integer: a = -23
    Dim b As Integer: b = 4
    ' int() は -∞方向への丸めなので不適切
    Console.WriteLine(fix(a / b) & ", " & a Mod b)
    return 0
  end function
end class

###############################################

========= Julia

a = 21
b = 4
# ハイブリッド(不適切な実装)
println(div(a, b), ", ", mod(a,b))
# ゼロ方向へ丸め(C などと同じ多数派)
println(div(a, b), ", ", rem(a,b))
# -∞方向へ丸め(Python などと同じだが少数派)
x = div(a, b)
println(x, a - x * b)

========= Perl

$a = 21;
$b = 4;
# ハイブリッド(不適切な実装)
print int($a / $b), ', ', $a % $b;
# ゼロ方向へ丸め(C などと同じ多数派)
print int($a / $b), ', ', $a - int($a / $b) * $b;
# -∞方向へ丸め(Python などと同じだが少数派)
$x = $a / $b
$x = int($x) - $x < 0 ? 1 : 0 
print $x, ', ', $a - $x * b;

###############################################

========= Haskell

main = do
    let a = 21
    let b = 4
    -- ゼロ方向へ丸め(C などと同じ多数派)
    putStrLn $ show(a `quot` b) ++ ", " ++ show(a `rem` b)
    -- -∞方向へ丸め(Python などと同じだが少数派)
    putStrLn $ show(a `div` b) ++ ", " ++ show(a `mod` b)

========= Python2

a = 21
b = 4
# -∞方向へ丸め(少数派)
print "%d, %d" % (a // b, a % b)

========= Python3

a = 21
b = 4
# -∞方向へ丸め(少数派)
print("%d, %d" % (a // b, a % b))

========= R

a = 21
b = 4
# -∞方向へ丸め(少数派)
cat(sprintf("%d, %d\n", a %/% b, a %% b))

========= Ruby

$a = 21
$b = 4
# -∞方向へ丸め(少数派)
print $a / $b, ', ', $a % $b

 

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

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

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