2023年10月17日火曜日

久々のJulia

プログラミングはAIに任せる時代になってしまったので,自分でコードを書くのは棋士の卵が詰め将棋の練習をしているようなことかもしれない。

Homebrewでmacにインストールされているソフトウェアを定期的に更新しているが,jupyterlabは,毎回,手動により brew link jupyterlab をすることを強いるのでうっとうしい。そんなこともあって,しばらくJuliaから足が遠のいていた。

鈴木貫太郎のYouTubeの数学の問題では,しばしば,整数の冪を比較するような問題が登場する。そこで,2^m と3^n が非常に近くなるような整数を探してみようと思った。m,nを1から順に条件を判定しながら増やしていけばよいかと思ったけれど,実際にコードを書いてみると,面倒なロジックは組まずに虱潰しに調べたほうが簡単そうであった。

久々にプログラミングすると,浮動小数点数から整数への変換がどうなっているかなど,基本的なところを忘れてしまっている。困ったものだ。これはconvert(T, x)だと書いてあったのだが,エラーになる。ChatGPTに相談してみたら,floor(T,x)とceil(T,x)を使いなさいとのことだった。その結果が次のコードである。
function dt(N,eps)
# N=1000000
# eps = 1.0e-6
ratio = log(2)/log(3)
    for i in 1:N
        jmin = floor(Int64,i*ratio)
        jmax = ceil(Int64,i*ratio)
        for j in jmin:jmax
            sol = i*log(2) - j*log(3)
            if abs(sol) < eps
                println("  2**",i,"/","3**",j," = ",exp(sol))
            end
        end
    end
end

for k = 1:8
    N=10^k
    eps=1/N
    println("N=",N," eps=",eps)
    @time(dt(N,eps))
end
N=10 eps=0.1
  2**8/3**5 = 1.0534979423868305
  0.000176 seconds (98 allocations: 2.750 KiB)
N=100 eps=0.01
  2**84/3**53 = 0.9979140462573083
  0.000160 seconds (97 allocations: 2.562 KiB)
N=1000 eps=0.001
  0.000003 seconds
N=10000 eps=0.0001
  2**1054/3**665 = 0.9999563468421858
  2**2108/3**1330 = 0.9999126955899699
  0.000351 seconds (207 allocations: 5.609 KiB)
N=100000 eps=1.0e-5
  2**50508/3**31867 = 0.9999927350845753
  0.000408 seconds (103 allocations: 2.656 KiB)
N=1000000 eps=1.0e-6
  2**301994/3**190537 = 1.0000000644940903
  2**603988/3**381074 = 1.0000001289881848
  2**905982/3**571611 = 1.0000001934822835
  0.003297 seconds (311 allocations: 8.562 KiB)
N=10000000 eps=1.0e-7
  2**301994/3**190537 = 1.0000000644940903
  0.027930 seconds (105 allocations: 4.938 KiB)
N=100000000 eps=1.0e-8
  2**85137581/3**53715833 = 0.9999999925494194
  0.264204 seconds (229 allocations: 17.953 KiB)

 いちおうできたことにしておこう。

0 件のコメント: