
AIにコードを別言語へ移植させる|挙動の差を見抜く確認手順
「サポートが切れる前に、この古いPythonのバッチをTypeScriptに書き直しておいて。AIを使えばすぐでしょ?」 実際、AIに渡すと数分でそれらしいコードが出てきます。ビルドも通る。ざっと動かしても、エラーは出ない。 なのに本番の数字と照らし合わせたら、合計が1円だけ合わない。原因を追うと、四捨五入の仕方が言語によって違っていた——。
こういうとき、「AIの移植は信用できない」と全部を手で書き直したくなりますよね。 でも、少し安心してください。移植でずれる場所には、ある程度決まったパターンがあります。 そして、それを見つける方法も、手順にしてしまえば難しくありません。
この記事では、AIにコードを別の言語へ移植させるときに、挙動の差を見抜くための確認手順を整理します。一度に全部やらなくて大丈夫です。今日は、移植したい関数をひとつ選ぶところから、一緒に進めていきましょう。
結論:AIによる移植で見るべきは「文法が正しいか」より「同じ入力に同じ出力を返すか」です。手順は4つ。①移植前に、今のコードの入出力を記録して固定する/②AIには小さな単位で移植させ、言語差で挙動が変わりうる箇所を書き出させる/③同じ入力を新旧両方に流して、出力を突き合わせる/④ずれが見つかったら、どちらを正とするかは人が決める。最初の一歩は①。比べる相手がいないと、ずれに気づけません。
何が起きているのか——文法は合っていても、言語の「当たり前」が違う
AIは、ある言語のコードを別の言語の文法に置き換えるのが得意です。ループはループに、関数は関数に、きれいに対応させてくれます。
ただ、言語には文法とは別に、それぞれの「当たり前」があります。
- 割り算や四捨五入の結果
- 「空っぽ」や「0」を真とみなすか偽とみなすか
- 文字列の長さの数え方
- 標準関数の細かいふるまい
見た目がそっくりな書き方でも、この「当たり前」が違うと結果が変わります。そしてAIは、見た目を似せることには強い一方で、元のコードが暗黙に頼っていた挙動まで、毎回引き継いでくれるとは限りません。
これはAIの手抜きというより、移植という作業そのものの難しさです。人が手で移植しても、同じところでつまずきます。だから「AIだから危ない」ではなく、移植には確認の型が要る、と考えるのが現実的です。
具体例:移植で結果が変わりやすい定番の差
よく出会うものを挙げます。どれも、エラーにはならずに静かに結果だけ変わるのが厄介なところです。
| 差が出る所 | 例 | 何が起きるか |
|---|---|---|
| 負の数の割り算・余り | Pythonの -7 // 2 は -4、Javaの -7 / 2 は -3。余りもPythonの -7 % 2 は 1、Javaは -1 | マイナスを含む計算(返品・調整額など)だけずれる |
| 四捨五入 | Python 3の round(2.5) は 2(偶数への丸め)、JavaScriptの Math.round(2.5) は 3 | 金額・ポイント計算で1ずれる |
| 真偽の判定 | PHPでは文字列 "0" が偽、Pythonでは "0" は真 | 条件分岐の向きが変わる |
| 並べ替え | JavaScriptの [10, 9, 1].sort() は、比較関数がないと文字列として並べて [1, 10, 9] | 数値の並び順が崩れる |
| 文字列の長さ | 絵文字1文字が、Pythonの len では1、JavaScriptの length では2 | 文字数チェックや切り詰めがずれる |
| 文字列の分割 | "a,b,,".split(",") が、Pythonでは空文字を残して4要素、Javaでは末尾の空文字を捨てて2要素 | CSVの列数がずれる |
| 整数の大きさ | Pythonの整数は桁あふれしないが、Javaの int は約21億を超えるとあふれる | 大きな件数・金額だけおかしくなる |
| 日付 | JavaScriptの Date は月を0から数える | 1か月ずれる(詳しくは日付・タイムゾーン処理の確認手順) |
| 並び順の保証 | Goの map は、くり返すたびに順番が変わりうる | 出力の順番が実行ごとに変わる |
全部を覚えておく必要はありません。「こういう種類の差がある」と知っておくだけで、確認するときの目の付け所が変わります。
放っておくと、何が起きるか
移植のずれは、テストデータがきれいなうちは表に出てきません。
- 普段の入力では一致して、特殊な入力でだけずれる:マイナス値、ちょうど0.5、絵文字、空欄、大きな数。本番で初めて出会うことが多い値です。
- 気づくのが遅れるほど、直す範囲が広がる:ずれた数字が帳票や他システムに流れたあとだと、データの修正まで必要になります。
- 「移植のせいか、元からか」が分からなくなる:比べる記録がないと、問い合わせが来たときに原因を切り分けられません。
逆に、移植前に「今の挙動」を記録しておけば、ずれは移植した直後、手元で見つけられます。ここが、この記事でいちばん伝えたいところです。
移植の確認手順4ステップ

ステップ1:移植する前に、今の入出力を記録して固定する
まず、移植する前のコードに、いくつもの入力を流して、出てきた出力をそのまま記録します。仕様書が正しいかどうかではなく、「今のコードが実際にこう動いている」という事実を残すのが目的です。
- 普段のデータ(本番に近いものを、個人情報を伏せて)
- 先ほどの表に出てきた「ずれやすい値」:マイナス、0、ちょうど0.5、空欄、絵文字、とても大きな数、月末・年末の日付
- 過去に障害や問い合わせがあった入力
入力の候補出しはAIに手伝ってもらえます(境界値・異常系をAIに考えさせる手順も参考にどうぞ)。ただし、期待する出力はAIに書かせず、旧コードを実際に動かして取るのがポイントです。AIが想像した答えでは、比べる意味がなくなってしまいます。
元のコードの仕様がそもそもはっきりしないときは、先にレガシーコードの仕様をAIに読み解かせる流れで、ざっくり把握しておくと進めやすくなります。
ステップ2:小さな単位で移植させ、「差が出そうな所」を書き出させる
ファイルを丸ごと渡すより、関数ひとつ、処理ひとつの単位で移植させるほうが、ずれを見つけやすくなります。
そして、コードと一緒に「言語差で挙動が変わりうる箇所」を書き出してもらいます。たとえばこんな頼み方です。
次の Python の関数を TypeScript に移植してください。
## 守ってほしいこと
- 元のコードと「同じ入力に同じ出力を返す」ことを最優先にしてください
- 読みやすさのための書き換えや、ついでの改善はしないでください
## 移植のあとに出してほしいもの
- 言語の違いで挙動が変わりうる箇所の一覧
(割り算・余り、四捨五入、真偽判定、文字列の長さや分割、
数値の大きさ、日付、並び順、例外の扱い など)
- それぞれについて、元の挙動に合わせるために何をしたか
- 自信がない箇所は「自信がない」と書いてください
(ここに元のコード)
この一覧は、AIが「ここは気をつけました」と自己申告しているだけなので、正しいとは限りません。それでも、人が確認する場所の地図として役に立ちます。
ステップ3:同じ入力を新旧に流して、出力を突き合わせる
ステップ1で記録した入力を新しいコードにも流し、出力を機械的に比べます。目で見比べるより、差分を出すほうが確実です(比べ方の考え方は差分(diff)の用語解説も参考になります)。
- 一致した入力は、ひとまず安心してよい範囲
- 一致しなかった入力は、ステップ2の一覧と照らし合わせて原因を探す
- 小数は、どこまでの桁が一致していればよいかを先に決めておく
比べるための入出力の記録は、そのまま新しいコードのテストとして残せます。AIが書いたテストを確認するコツはAIが書いた単体テストの確認ポイントにまとめています。
ステップ4:ずれが見つかったら、どちらを正とするかは人が決める
ずれの中には、実は元のコードのほうがおかしかった、というものも混じります。
たとえば「旧コードの四捨五入が、実は業務ルールと違っていた」という場合。新しいコードで正しく直すと、過去の帳票と数字が合わなくなります。
- 元の挙動をそのまま引き継ぐか
- この機会に正しい挙動に直すか
これは技術の問題ではなく、業務の判断です。AIに決めさせず、関係者と相談して、決めた理由を残しておくのがおすすめです。移植と仕様の変更を同時にやると、ずれの原因が追えなくなるので、直すとしても「移植」と「修正」は別の変更に分けると、後から自分が助かります。
明日やること(小さく始める3つ)
- 移植したい関数をひとつ選び、入力を10個ほど流して出力を記録する:表の「ずれやすい値」を2〜3個混ぜてください。これだけで、移植の確認の土台ができます。
- AIへの頼み方に「差が出そうな所の一覧も出して」を一行足す:コードだけでなく、確認すべき場所の地図が手に入ります。
- 新旧の出力を差分で比べる小さなスクリプトを用意する:一度作れば、次の関数からも使い回せます。スクリプトの下書きもAIに頼めます。
AIによる移植 チェックリスト
【必須】の3つだけでも、静かなずれのかなりの部分を手元で拾えます。 残りは余裕があるときに。
- 【必須】移植前に、旧コードを実際に動かして入出力を記録したか(期待値をAIに書かせていないか)
- 【必須】同じ入力を新旧両方に流し、出力を機械的に比べたか
- 【必須】ずれが見つかったとき、どちらを正とするかを人が判断し、理由を残したか
- (余裕があれば)入力にマイナス・0・ちょうど0.5・空欄・絵文字・大きな数・月末の日付を含めたか
- (余裕があれば)関数・処理ごとの小さな単位で移植させたか
- (余裕があれば)AIに「言語差で挙動が変わりうる箇所」の一覧を出させ、確認したか
- (余裕があれば)移植と同時に、ついでの改善や書き換えが混ざっていないか
- (余裕があれば)小数を比べるときの許容する桁数を決めたか
- (余裕があれば)例外・エラーの扱い(例外を投げるか、値を返すか)が元と揃っているか
- (余裕があれば)比べた入出力を、新しいコードのテストとして残したか
最後に
移植で数字が1円ずれたとき、それはあなたの確認が甘かったからではありません。言語が違えば「当たり前」が違う。それだけのことです。 そして、今のコードの答えを先に記録しておく——このひと手間があれば、ずれはもう怖いものではなく、「見つけて直せるもの」になります。

AIに書き直してもらうこと自体は、とても良い使い方です。人が確かめる場所さえ決めておけば、移植はずっと速く、ずっと落ち着いて進められます。 まずは明日、移植したい関数をひとつ選んで、10個の入力を流してみてください。そこから始めましょう。
よければ、こちらも
- レガシーコードの仕様をAIに読み解かせる|仕様復元の進め方
- 境界値・異常系をAIに考えさせて漏れを減らす手順
- AIに日付・タイムゾーン処理を書かせる|ズレる定番バグの確認手順
- AIリファクタリングの差分レビュー|壊さず確認する手順
- AIが書いた単体テストを信用しすぎない|確認ポイント