金額の精度と小数位:スワップで「少し少ない」が高くつく場所
2026年10月25日、19と19.9 USDTで元本4.7%差・受取11.0%差、100と100.000001は最後の桁まで同一。答えを整形するコードを読み、受取8桁・レート有効8桁・読むそばから動く上下限を確認します。
「少し少ない」には二種類ある。 2026年10月25日18:06:17 UTC、当サイトの見積エンドポイントは19 USDT-TRC20を0.01334439 XMRと評価しました。2秒後の19.9 USDTは0.01481818。金額にして4.7%増で、モネロは11.0%増えました。下限に貼り付いた位置では不足は比例では済みません。その40秒前、同じエンドポイントは100 USDTと100.000001 USDTを最後の桁まで同一に返していました。0.14598334 XMR、レート0.0014598334。1マイクロUSDTは何も動かさなかった。どちらも正しい結果で、二つ合わせて「少し少ない」の意味を決めています。下限を割れば高くつき、末尾の小数位では見えないのです。 (XMR→USDT 出口ルート)
どの資産にも分割できない最小単位がある。 1 BTCは100,000,000 satoshi、今日の80,703ドルなら1 satoshiは0.000807ドル。1 XMRは1,000,000,000,000 piconeroで、1 piconeroは0.0000000006ドル。1 ETHは10^18 wei、1 weiはおよそ0.0000000000000024ドル。ZECのzatoshiは1e-8、LTCのlitoshiも1e-8、SOLのlamportは1e-9、TRXのsunは1e-6、USDTはトロンでもイーサリアムでも6桁で最小単位は0.000001ドルです。これは表示の習慣ではなく、台帳が動かせる最小の数です。目にする見積はすべて、その整数個を丸めた版にすぎません。 (SOL to XMR guide)
見積は8桁で丸められる。 当サイトの見積ルートは受取量に `Number(best.toAmount.toFixed(8))`、レートに `Number(best.rate.toPrecision(8))` を返し、注文ルートも価格を固定するときに同じ8桁で書き込みます。先ほどの1マイクロUSDTが消えたのはこれで説明できます。0.000001 USDT × 約0.00146 は 1.5e-12 XMR、8桁目にはるか及びません。丸めによる最大の損失は0.00000001 XMR、今日の価格で約0.000006ドル。金額としては無視できますが、より重要なのは「約束」自体が小数8桁しか持たないという点です。向こう側のチェーンは整数を記録しています。 (XMR→USDT 出口ルート)
桁数は嘘をつく。 同じエンドポイントが1 XMRに595.698 USDT、レートに0.0014615927、上限に293.397277258162 XMRを出しました。三つの精度に見えますが、実際は二つの規則と一つの整形器です。レートは常に有効数字8桁なので小数位数は量級しだいで変わります。JSONの数値は末尾の0を落とすので、595.698は595.69800000です。小数点以下の桁を数えるのではなく規則を読みます。受取は小数8桁、レートは有効8桁、上下限は経路エンジンの出力そのまま——だから同じエンドポイントでモネロの上限は12桁、USDTの下限は6桁で返るのです。 (XMR→USDT 出口ルート)
上下限は読んでいる間にも動く。 18:02の時点でUSDT-TRC20→XMRの下限は19.801624、上限は176,509.209306。18:06には19.786762と176,443.886799、18:10には19.791362と176,464.859757になりました。誰もパラメータを触っていません。両方の境界は出金側から逆算され、レートに従って動きます。逆方向では上限が293.397277258162 XMR、下限が0.02974636でした。1トークンを投げると見積ではなく `amount below minimum` という構造化エラーが両方の境界付きで返ります。実務的な結論は単純です。ページからコピーした数字(この記事のものも含めて)はスナップショットであり、送金直前に取り直すべきものです。 (XMR→USDT 出口ルート)
その下の台帳は整数。 今日18:00:31 UTCのビットコインブロック973,103には25トランザクション、41出力。最大は2,449,754,800 satoshi、最小は0で金額を持たないOP_RETURN。ブロック全体の手数料は32,787 satoshi / 5,140 vB、6.379 sat/vBで約26.46ドルでした。トロンブロック87,426,048は536トランザクション、うち131がUSDT送金で、最小は3,375,404基本単位=3.375404 USDT、最大はちょうど100,000.000000。モネロブロック3,791,996は42トランザクション・87,296バイトで、報酬は600,030,720,000原子単位=0.60003072 XMR。どのチェーンも「3.375404個」を保存していません。整数を保存し、小数点は端で付ける表示上の決定です。 (XMR→USDT 出口ルート)
浮動小数点が実際に噛む場所。 Nodeで4行走らせればバグの種類が分かります。`0.1 + 0.2` は0.30000000000000004。`1.15 * 100` は114.99999999999999——「Max」ボタンが残高に価格を掛けると、残高よりわずかに少なく、さらに悪いことに下限よりわずかに少ない値ができます。`(0.000181501).toFixed(8)` は0.00018150を返し、9桁目を拒否せず黙って捨てます。そして10^18 weiは2^53より大きいので、JavaScriptはweiを正確に数えられません。その量級では最大安全整数に1を足しても同じ数が返ります。だから金額は整数か文字列で持ち、表示する瞬間だけ小数にするのです。
精度のための6ステップ。 1)計算の前に最小単位へ直す。100 USDTは100,000,000単位、1 XMRは1,000,000,000,000 piconero。2)実際に送る純額で考える。取引所の出金は先に手数料を引くので、純額を読む。3)「Max」をそのまま見積金額にしない。浮動小数点の引き算で、 residue が残る。4)下限から測れる一段上を取る。下限19.79なら20を送る。下限は動き、拒否されれば1分を失う。5)資産自身の精度を超えない。BTCの9桁目は存在しないので、丸めた側が捨てる。6)照合は整数で。XMRの1e-8差は0.000006ドルだが、100 USDT入金の1e-6差はもう申告した額とは別の金額です。 (XMR→USDT 出口ルート)
窓口でこれが意味すること。 スワップの精度とは12桁を暗唱できることではなく、目の前のどの数字が正確なのかを知ることです。チェーンの整数、注文に書かれた小数8桁の約束、有効8桁のレート、そして動き続ける上下限。19と19.9 USDTの差は受取量の11%。100と100.000001の差はゼロで、それは答えの分解能より小さいからです。同じ物理で、見分けがつけば間違った方に払わなくなります。自分の量で見積を取り、下限を確認し、純額を送り、実際に受け取った整数で8桁の約束を照合してください。 (XMR→USDT 出口ルート)