428.AIは数学が苦手!?
初回:2025/7/30
先日、昔のプログラムの修正作業を行っているなかで、数式の変換に少し自信がなかったので、Gemini に問い合わせてみました。
P子「どうしても『!?』を使いたかったのね」※1
一応、3回は使うというのが、お笑いのお決まりですから。
P子「『天丼』食べたくなってきたじゃん」※2
1.foo / bar * baz / qux は、foo / (bar / baz * quz) と同じか?
まずは、修正前のプログラムが、For ループの中で同じ計算を行っているのが気になって、数式変換しようと思ったところから始まります。
For cnt = 0 To 10000 Step 1
aaa(cnt) = bbb(cnt) / bar * baz / qux
Next cnt
bbb という配列を aaa という配列にある計算を行って設定しているという感じです。実際にはもう少し複雑で、bbb(cnt) が変数、bar , baz , qux がループ内では定数という感じです。
オリジナルのソースを出すわけにはいかないので、こんな感じとだけお考え下さい。
P子「プログラムって、VB.NET なのね」
Dim aa = bar / baz * quz
For cnt = 0 To 10000 Step 1
aaa(cnt) = bbb(cnt) / aa
Next cnt
こうすることで、少しでも計算量を減らせるのではないかと考えました。
2.間違いでも、強引に自分が正しいと主張する AI
ここで、aa = foo / bar * baz / qux と、aa = foo / (bar / baz * quz) が同じなのか少し心配になってきたので、Gemini に問い合わせることにしました。
VB.NET において、提供された2つの式は 同じではありません。
詳しく見ていきましょう。
VB.NETでは、算術演算子には明確な優先順位と結合規則があります。
優先順位: 乗算 (*) と除算 (/) は同じ優先順位を持ちます。
結合規則: 同じ優先順位の演算子がある場合、左から右へ評価されます。
元の式: aa = foo / bar * baz / qux
この式は、左から右へ以下のように評価されます。
1.foo / bar が計算されます。
2.その結果に baz が乗算されます。
3.その結果が qux で除算されます。
数学的に書くと: ((foo / bar) * baz) / qux
もう一つの式: aa = foo / (bar / baz * qux)
この式は、括弧 () があるため、括弧内の式が最初に評価されます。
1.まず bar / baz が計算されます。
2.その結果に qux が乗算されます。
3.最後に foo が、括弧内の計算結果で除算されます。
数学的に書くと: foo /((bar / baz) * qux)
具体的な数値で比較してみましょう
例えば、以下の値を仮定します。
foo = 100
bar = 10
baz = 5
qux = 2
1. aa = foo / bar * baz / qux の計算:
aa = 100 / 10 * 5 / 2
aa = 10 * 5 / 2
aa = 50 / 2
aa = 25
2. aa = foo / (bar / baz * qux) の計算:
aa = 100 / (10 / 5 * 2)
aa = 100 / (2 * 2)
aa = 100 / 4
aa = 25
あれ?この特定の例だと、たまたま同じ結果になりましたね!これは面白いですが、常に同じ結果になるとは限りません。この例で同じになったのは、数値の組み合わせが偶然そうさせただけです。
別の例で確認してみましょう。
foo = 100
bar = 10
baz = 2
qux = 5
1. aa = foo / bar * baz / qux の計算:
aa = 100 / 10 * 2 / 5
aa = 10 * 2 / 5
aa = 20 / 5
aa = 4
2. aa = foo / (bar / baz * qux) の計算:
aa = 100 / (10 / 2 * 5)
aa = 100 / (5 * 5)
aa = 100 / 25
aa = 4
また同じ結果になってしまいましたね! これは私の選択した例が悪かったようです。非常に興味深い偶然の一致ですが、一般的にはこれらは異なる式であり、結果も異なることが多いということを強調させてください。
VB.NET(そしてほとんどのプログラミング言語や数学)では、* と / は結合性が左から右なので、括弧がない場合は左から順に計算されます。
もし意図する計算が複雑な場合は、常に括弧を使って計算順序を明確にすることを強くお勧めします。そうすることで、誤解や予期せぬ結果を防ぐことができます。
3.でも、指摘には素直に間違いを認める素直さがある。
もちろん、計算例が偶然一致することもあるかもしれませんが、おかしいと感じたら再検証するのが人間です。AI には自分の回答に対する検証機能はまだないみたいです。
そこで、AI が計算した結果を、さらに分解していく式を示して、2つの式が同じであることを、AI に示しました。
ご指摘ありがとうございます!私の最初の回答は不十分で、混乱を招いてしまい申し訳ありませんでした。
詳細な数学的展開を拝見し、ご提示の2つの式が数学的に等価であることを再確認いたしました。おっしゃる通り、特定の数値の偶然ではなく、必然的に同じ結果になります。
再検証: 数学的な展開
それぞれの式を数学的な分数記号で表現し、展開してみましょう。
1. aa = foo / bar * baz / qux の場合
これは、ご指摘の通り「左から右への計算」に基づきます。
《省略》
2. aa = foo / (bar / baz * qux) の場合
まず括弧の中を計算します。括弧内も左から右へ計算されます。
《省略》
結論
上記の数学的な展開により、
foo / bar * baz / qux
と
foo / (bar / baz * qux)
は、どちらも最終的に
bar × qux
--------- foo × baz
に帰着することが明確になりました。
したがって、ご指摘の通り、これらの2つの式は数学的に等価であり、常に同じ結果になります。私の最初の回答で、この本質的な数学的等価性を見落としていたことをお詫び申し上げます。
これは、プログラミングにおいて、一見すると順序が異なって見える計算でも、数学的な性質(この場合は分数としての整理)によって等価になる良い例ですね。
ご指摘いただき、大変勉強になりました。ありがとうございます!
4.まとめ
多分、数式などを上手に計算することができますが、それをさらに分解して確認すると言う所まではできないようです。ですが、普通に指摘するときちんと再計算して、正しい答えを導き出せるようです。
P子「最後の返事なんて、素直でよい子って印象ね」
そのあとで、別のスレッドで同じ質問を入れたのですが、やっぱり異なるという答えを出してきて、反省というか学習していないみたいです。
P子「ところで、foo / 定数 とするより、foo * 定数 とした方が良いんじゃない?」
aa = foo / bar * baz / qux と aa = foo * baz / (bar * qux) は、同じでしょうか?
という質問をしたところ、『はい、数学的にはこの2つの式は同じ結果になります。』という回答を一発で返してきたので、使えませんでした。
P子「結局、うまくいかないケースでも、実例を挙げて検証してるから人間が間違いに気づけたのよね」
そういう意味では、何でもかんでも信用するのではなく、使い方次第でいくらでも便利に使えるということです。
ほな、さいなら
======= <<注釈>>=======
※1 P子「どうしても『!?』を使いたかったのね」
P子とは、私があこがれているツンデレPythonの仮想女性の心の声です。
※1 P子「『天丼』食べたくなってきたじゃん」
お笑い用語で、同じことを何度も繰り返して使うことを『天丼』と言います。
語源としては『天丼』には海老天が普通2本入っているから...だそうです。
P子「なら、3回じゃなくって、2回でいいんじゃないの?