pepe’s blog

雑多な趣味に関して深く浅く広く狭く語るブログです。

ChatGPT にプログラムを作らせてみた ~円周率編~

ChatGPTにお願いするとプログラムを生成してくれるというので試してみました。なお、プログラミング言語としてはWScript *1 を指定しました。

ChatGPT が生成した円周率を計算するプログラム

"円周率を計算するWscriptを教えてください" と質問を投げてみたところ、以下のような回答が表示されました。

円周率を計算するWscriptを作成する方法はいくつかありますが、以下に一例を示します。このWscriptでは、マチンの公式を使用して円周率を計算します。

Set objShell = WScript.CreateObject("WScript.Shell")

' 計算する桁数を指定
n = 1000

' マチンの公式に基づいて円周率を計算
pi = 4 * ATan(1) - 4 / (5 * ATan(1)) - 4 / (239 * ATan(1))
For i = 1 to n - 1
    pi = pi + 4 / ((2 * i + 1) * (2 * i + 2) * (2 * i + 3)) * (-1) ^ i
Next

' 計算結果を表示
objShell.Popup "円周率の計算結果:" & CStr(pi)

このWscriptを実行するには、テキストエディターで上記のコードをコピーして、"pi_calculator.vbs"のような名前で保存します。その後、保存したファイルをダブルクリックして、Wscriptで実行します。円周率の計算結果が表示されます。なお、nの値を変更することで、より高い精度で円周率を計算することができます。

もう一度同じ質問を投げてみた

つぎに、もう一度同じ質問を投げてみたところ、今度は以下のような回答が表示されました。

円周率を計算するWscriptは、以下のようになります。このスクリプトでは、レヴィ=チヴィタの公式を使用して円周率を計算しています。

Set objShell = WScript.CreateObject("WScript.Shell")

' 計算する桁数を指定
n = 1000

' レヴィ=チヴィタの公式に基づいて円周率を計算
pi = 0
For i = 0 To n
    pi = pi + ((-1) ^ i / (2 * i + 1))
Next
pi = pi * 4

' 計算結果を表示
objShell.Popup "円周率の計算結果:" & CStr(pi)

このWscriptを実行するには、テキストエディターで上記のコードをコピーして、"pi_calculator.vbs"のような名前で保存します。その後、保存したファイルをダブルクリックして、Wscriptで実行します。円周率の計算結果が表示されます。nの値を変更することで、より高い精度で円周率を計算することができます。

言い回しを変えて質問を投げてみた

今度は少し言い回しを変えて「別のプログラム」とそっけない質問を投げてみたところ、以下のような回答が表示されました。

別の方法として、以下のWscriptを使用することもできます。このスクリプトでは、モンテカルロ法を使用して円周率を計算します。

Set objShell = WScript.CreateObject("WScript.Shell")
Randomize

' 計算する点の数を指定
n = 1000000

' 円の内部に点が存在するかどうかを判定して、円周率を計算
count = 0
For i = 1 To n
    x = Rnd()
    y = Rnd()
    If x ^ 2 + y ^ 2 <= 1 Then
        count = count + 1
    End If
Next
pi = 4 * count / n

' 計算結果を表示
objShell.Popup "円周率の計算結果:" & CStr(pi)

このWscriptを実行するには、テキストエディターで上記のコードをコピーして、"pi_calculator.vbs"のような名前で保存します。その後、保存したファイルをダブルクリックして、Wscriptで実行します。円周率の計算結果が表示されます。nの値を変更することで、より高い精度で円周率を計算することができますが、点の数を増やすと計算に時間がかかることに注意してください。

さらに言い回しを変えてみた

さらに言い回しを変えて「もっと違うプログラム」と質問を投げてみたところ、以下のような回答が表示されました。

以下は、数列を使用して円周率を計算するWscriptの例です。このスクリプトでは、ニルカンタの方法を使用して円周率を計算します。

Set objShell = WScript.CreateObject("WScript.Shell")

' 計算する項数を指定
n = 1000

' ニルカンタの方法に基づいて円周率を計算
a = 1
b = 1 / Sqr(2)
t = 1 / 4
pi = (a + b) ^ 2 / (4 * t)
For i = 1 to n
    a_new = (a + b) / 2
    b_new = Sqr(a * b)
    t_new = t - (a - a_new) ^ 2 * t / (4 * b)
    pi = (a_new + b_new) ^ 2 / (4 * t_new)
    a = a_new
    b = b_new
    t = t_new
Next

' 計算結果を表示
objShell.Popup "円周率の計算結果:" & CStr(pi)

このWscriptを実行するには、テキストエディターで上記のコードをコピーして、"pi_calculator.vbs"のような名前で保存します。その後、保存したファイルをダブルクリックして、Wscriptで実行します。円周率の計算結果が表示されます。nの値を変更することで、より高い精度で円周率を計算することができます。ただし、ニルカンタの方法は、各項の計算に時間がかかるため、nの値が大きい場合は計算に時間がかかることがあります。

別のスクリプト言語を指定してみた

VBScipt による回答が続いたので、今度は別のスクリプト言語として「JScriptで」と質問を投げてみたところ、以下のような回答が表示されました。

JScriptで円周率を計算する例を示します。
以下のスクリプトでは、ライプニッツの公式を使用して円周率を計算しています。

var n = 1000; // 計算する項数
var pi = 0;
for (var i = 0; i < n; i++) {
    var sign = i % 2 == 0 ? 1 : -1;
    pi += sign * (1 / (2 * i + 1));
}
pi *= 4;

WScript.Echo("円周率の計算結果:" + pi);

このスクリプトでは、まず計算する項数をnに設定します。次に、ループを使用して、ライプニッツの公式に基づいて円周率を計算します。最後に、計算結果をWScript.Echoで表示します。

別の方法として、モンテカルロ法を使用する例を示します。

var n = 1000000; // 計算する点の数
var count = 0;
for (var i = 0; i < n; i++) {
    var x = Math.random();
    var y = Math.random();
    if (x * x + y * y <= 1) {
        count++;
    }
}
var pi = 4 * count / n;

WScript.Echo("円周率の計算結果:" + pi);

このスクリプトでは、まず計算する点の数をnに設定します。次に、ループを使用して、ランダムに生成された点が円の内部にあるかどうかを判定し、内部にある点の数を数えます。最後に、内部にある点の割合から円周率を計算して、計算結果をWScript.Echoで表示します。

アバウトな要望をしてみた

アバウトな文言として「もっと」と質問を投げてみたところ、以下のような回答が表示されました。

JScriptで円周率を計算する別の例を示します。

以下のスクリプトでは、レーマーの方法を使用して円周率を計算しています。

var n = 1000; // 計算する項数
var s = 0;
for (var i = 0; i < n; i++) {
    var x = Math.random();
    var y = Math.random();
    s += Math.sqrt(x * x + y * y) <= 1 ? 1 : 0;
}
var pi = 4 * s / n;

WScript.Echo("円周率の計算結果:" + pi);

このスクリプトでは、まず計算する項数をnに設定します。次に、ループを使用して、ランダムに生成された点が円の内部にあるかどうかを判定し、内部にある点の数を数えます。最後に、内部にある点の割合から円周率を計算して、計算結果をWScript.Echoで表示します。ただし、このスクリプトでは、レーマーの方法による円周率の計算は、モンテカルロ法よりも計算に時間がかかることに注意してください。

また、ニルカンタの方法を使用する例も以下に示します。

var n = 1000; // 計算する項数
var a = 1;
var b = 1 / Math.sqrt(2);
var t = 1 / 4;
var pi;
for (var i = 0; i < n; i++) {
    var a_new = (a + b) / 2;
    var b_new = Math.sqrt(a * b);
    var t_new = t - Math.pow(a - a_new, 2) * t / (4 * b);
    pi = Math.pow(a_new + b_new, 2) / (4 * t_new);
    a = a_new;
    b = b_new;
    t = t_new;
}

WScript.Echo("円周率の計算結果:" + pi);

このスクリプトでは、まず計算する項数をnに設定します。次に、ループを使用して、ニルカンタの方法に基づいて円周率を計算します。最後に、計算結果をWScript.Echoで表示します。

Leibnizの公式を指定してみた

つぎに「Leibnizの公式で」と質問を投げてみたところ、以下のような回答が表示されました。

Leibnizの公式を使用して円周率を計算するJScriptの例を以下に示します。

var n = 1000; // 計算する項数
var pi = 0;
for (var i = 0; i < n; i++) {
    var sign = i % 2 == 0 ? 1 : -1;
    pi += sign * (1 / (2 * i + 1));
}
pi *= 4;

WScript.Echo("円周率の計算結果:" + pi);

このスクリプトでは、まず計算する項数をnに設定します。次に、ループを使用して、Leibnizの公式に基づいて円周率を計算します。最後に、計算結果をWScript.Echoで表示します。

Leibnizの公式は、以下のように表されます。

この公式では、無限に続く級数を有限の項数で打ち切って円周率を求めることができます。ただし、Leibnizの公式による円周率の計算は、他の方法に比べて収束が遅く、項数を増やす必要があるため、計算に時間がかかることがあります。

なお、この回答例は「別のスクリプト言語を指定してみた」の項で提示されたプログラムと同じものです。

Math.pow関数の使用を指定してみた

前述の回答に対して「Math.pow を使って」という追加の指定を投げてみたところ、以下のような回答が表示されました。

Math.powを使用して円周率を計算するJScriptの例を以下に示します。

var n = 1000; // 計算する項数
var pi = 0;
for (var i = 0; i < n; i++) {
    var term = Math.pow(-1, i) / (2 * i + 1);
    pi += term;
}
pi *= 4;

WScript.Echo("円周率の計算結果:" + pi);

このスクリプトでは、まず計算する項数をnに設定します。次に、ループを使用して、Math.powを使用して項を計算し、円周率を計算します。最後に、計算結果をWScript.Echoで表示します。

Math.pow関数は、第一引数に底となる数を、第二引数に累乗する値を指定して、べき乗を計算します。このスクリプトでは、-1のi乗を計算するためにMath.pow関数を使用しています。

Leibnizの公式は、以下のように表されます。

この公式では、無限に続く級数を有限の項数で打ち切って円周率を求めることができます。ただし、Leibnizの公式による円周率の計算は、他の方法に比べて収束が遅く、項数を増やす必要があるため、計算に時間がかかることがあります。

ChatGPT による回答の画面キャプチャ

参考までに、本稿に掲載した ChatGPT による回答の画面キャプチャを以下に貼っておきます(画像をクリックすると拡大表示されます)。

感想

名前に "Chat" と付くだけあって、前出の質問&回答をもとに次の回答を別の形で提示するという高度な処理をおこなっていることに驚きました。
実は今回の質問以外にもハードウェア制御を伴う簡単なプログラムを各種のプロセッサ別に生成してみたのですが、かなりマイナーなプロセッサでもプログラムのソースコードが吐き出されることにビックリしました。*2

脚注・コメント

*1:WScript は Windows に標準搭載されているスクリプト言語です。JavaScript 系の JScript と BASIC 系の VBScript が標準で利用可能です。

*2:ニーモニックがない i4004 を指定したらバイナリダンプが表示されました!