tatsu456

旅行の割り勘で、為替レートをいつ確定させるか

最終更新 2026年8月31日

五日間の旅行で、初日の宿は現地通貨、二日目の食事は同行者のカードでドル建て、最終日の土産はまた別の通貨。帰ってきて「じゃあ精算しよう」となったとき、最初に引っかかるのは金額ではなくレートです。旅行中ずっと為替は動いています。初日のレートで割るのか、帰国した日のレートで割るのか、それともカードの明細が届くまで待つのか。

この問いに絶対の正解はありませんが、「どこで止めれば全員に説明がつくか」という選び方はあります。多通貨の割り勘アプリ SplitBill_EX の実装を読み、レートをいつ取り、いつ止め、取れなかったときに何を使っているかを、理屈ごと追いかけます。

動くレートを、どの時点で止めるかレート表は「1米ドルあたり」で持つ取れなかったときに何を使うか確定するのは「締めた」瞬間引くための表

動くレートを、どの時点で止めるか

やり方は大きく二つです。ひとつは、支払いを記録するたびにその日のレートで自国通貨に直して控えておく方式。もうひとつは、支払いは現地通貨のまま記録しておき、精算するときに一本のレートでまとめて換算する方式です。

SplitBill_EX は後者です。一件の支払いに保存されるのは、金額と通貨コード、日付や支払った人、それに手数料・税・チップ・個別の貸し借りといった明細で、レートを書き込む欄だけがありません。換算はそのつど手元のレート表を使って行われ、結果が支払いの記録に焼き付くことはありません。お会計の入力画面でも、1人あたりの額や貸し借りは精算通貨に換算されて表示されますが、残るのは元の通貨のままの金額です。

なぜ一本にまとめるのか。割り勘が答えるべき問いは「誰が誰にいくら渡すか」という一つだけです。同じレート表で全件を換算すれば、誰がどの日に立て替えたかという偶然が結果に入り込みません。支払いごとに違う日のレートを当てると、たまたま自国通貨が弱い日に立て替えた人だけが有利、あるいは不利になります。誰がどの日に財布を出したかは、本来その人の手柄でも失点でもありません。

ただし、表を一本にしても金額が動かなくなるわけではありません。通貨ごとに動き方が違えば、表を新しくするたびに送金額そのものは変わります。だからどこかで表を一つに決めて止める必要があり、その話は後半に出てきます。

逆の言い分もあります。日ごとに換算したほうが、実際に財布から出ていった自国通貨には近い。ただしカードで払った分は、カード会社が独自の時点と条件で請求してくるので、どうやっても一致しません。そこを追いかけるより、レートと手数料を分けるほうが破綻しません。実装でも、為替手数料とカード手数料は「レート」ではなく手数料の行として扱われ、税やチップを足したあとの金額に乗ります。手数料は率や額として説明できますが、レートは説明のしようがないからです。

レート表は「1米ドルあたり」で持つ

保持しているレート表は「1米ドルが各通貨で何単位か」という形です。円からユーロのような組み合わせも、いったん米ドルを経由し、金額を元通貨のレートで割ってから先の通貨のレートを掛けて求めます。

この形にする理由は表の大きさです。扱う通貨は30。直接のペアで持つなら 30×29 で870通りの数字を毎回取りに行くことになりますが、米ドル基準なら30個で足ります。

代わりに、すべての換算が米ドルを一度通ります。ここで効いてくるのが数値の型で、レートは小数の二進表現を持ち込まない Decimal で扱われ、取得した値もいったん文字列を経由して変換されます。157 が 157.00000000000003 のような値になると、往復させたときに元へ戻らず、換算のたびに端の桁がずれていくためです。テストでは、100米ドルを円に直して戻すと元の100に戻ることを確かめています。

もうひとつ、表に載っていない通貨コードが来たときは、金額をそのまま素通しします。換算できないことを理由に誰かの支払いを0にするほうが、換算されないまま残るよりはるかに危ないからです。

取れなかったときに何を使うか

レートは起動時に一度だけ、open.er-api.com の米ドル基準の一覧に問い合わせて取得します。打ち切りは8秒。端末のキャッシュは使わず取り直し、接続が戻るのを待つ設定も切ってあります。割り勘の画面は、開いた瞬間に使えないと意味がないからです。レートが少し古くても計算そのものは始められます。

自動で取り直す仕組みはこれ以外にありません。設定画面に手動の更新ボタンがあるだけです。裏を返せば、宿に戻って電波が安定したときに一度押しておく、という運用が素直に効きます。

受け取った応答は素通ししません。HTTPが200番台であること、応答が成功を名乗っていること、扱う30通貨のうち値が正のものだけを採ったうえで、米ドルが含まれ、5通貨以上そろっていること。ひとつでも欠ければ丸ごと捨てて前の表を使い続けます。半分だけ更新すると、通貨ごとに取得時点の違う表ができあがるからです。混ざった表は、特定の二通貨の間だけ狂うという、いちばん気づきにくい壊れ方をします。

結果として、レートの出所は三段になります。この起動で取れた「最新」、前回までに取れていた「保存済み」、一度も取れていないときの「内蔵」です。内蔵は30通貨ぶんの概算値をアプリ自身が持っているもので、1米ドルが157円、0.92ユーロ、16,200ルピアといった水準です。取得時刻を持たないので、画面の更新時刻は「—」になります。

細かいところでは、一度「最新」だった表は、次の取得に失敗した時点で「保存済み」に落とされます。数字も取得時刻も変わらず、ラベルだけが変わる。この起動で取れた数字ではない、というのは数字を見ても分からないからです。内蔵レートは、次回のために持ち越すレート表としては保存されません。取得できた値ではない概算を、最新のレートとして残さないためです。ただし内蔵レートのまま精算を締めた場合、その値は精算の記録の一部として残ります。

確定するのは「締めた」瞬間

旅行中、金額は固定されません。支払いを足すたび、レートを更新するたび、精算額はそのときのレートで全件が計算し直されます。止まるのは、精算を締めたときです。

締めると、参加者・支払い・通貨の設定・そのときのレート表・確定した送金額がひとまとまりで保存されます。過去の精算の画面は、その送金額をそのまま表示するだけで再計算しません。CSVに書き出すときも、そこに保存されたレート表を使います。半年後に開いても同じ数字が出るのは、そのためです。

過去の精算を復元して続きを入力するときだけ、例外があります。手元のレートが内蔵の概算しかない場合に限り、保存されていたレートを採ります。これから足す支払いは今のレートで換算されるべきですが、手元に概算しかないなら、当時実際に取得できた値のほうが確からしいからです。

共有機能で複数人が同じ部屋にいる場合、レート表は共有されません。流れるのは人・支払い・設定と、確定した精算です。締める前は端末ごとに末尾の数字が違うことがあり、確定した数字は締めた人の端末のレートで作られて全員に配られます。実務的な結論はひとつで、締める操作は一人が、電波のあるところで、更新してから行うことです。

端数の話も同じ場所で決まります。送金額は精算通貨の小数桁で四捨五入され、最小単位の半分に満たない残りは送金になりません。円・ウォン・ドン・ルピアは小数桁を持たない扱いなので、円で締めれば1円未満は出ません。締める通貨は、全員が実際に手渡しや送金でやり取りする通貨にしておくのが安全です。

引くための表

レートの出所と、その扱い
出所そうなる条件端末に保存画面の見え方
最新この起動、または更新ボタンで取得に成功したされる「最新」と、取得からの経過時間
保存済み今回は取れず、前回までに取れた表を使っている。取得に失敗すると最新から降格するされる「保存済みレート」と、取得からの経過時間
内蔵一度も取得に成功していない。30通貨の概算値されない「内蔵レート」と、更新時刻は「—」
場面ごとに、どの時点のレートで計算されるか
場面使われるレート
お会計を入力している最中いま端末が持っている表。換算後の額は表示されるだけで、記録には残らない
旅行中に途中経過を見るいま端末が持っている表。更新すればその場で全件が計算し直される
精算を締める締めた端末がそのとき持っている表。人・支払い・設定・レート・送金額ごと保存される
過去の精算を開く計算し直さない。保存された送金額をそのまま表示
過去の精算をCSVに出すその精算に一緒に保存されているレート表
過去の精算を復元して続けるいまのレート。手元が内蔵レートのときだけ、保存されていたレートを採る
オフラインで締める直前に取得できた表。「最新」でないことはバッジに出る

アプリを使わない場合でも、判断の順序は同じです。支払いは現地通貨のまま控えておく。手数料はレートに混ぜず別の行にする。締める日を決めて、その日のレートを一本に決め、決めた値を全員が見える形で書き残す。書き残しさえすれば、あとで為替がどう動いても、精算をやり直す理由はなくなります。