floor関数の結果が期待と異なる場合(浮動小数点の精度の計算問題)の対処法

以下のようなデータフレームがあったとします。

「計算を作成」を使って floor(数量 * 料率) を計算すると、期待値より 1 小さい値が返ることがあります。

例えば、受注 ID 001の計算結果は1521 ではなく 1520 になります。

この理由を順を追って説明していきます。

まず、floor() を使わずに 数量 * 料率 だけで列を作ってみます。

結果の列を確認すると、受注 ID 001の値は 1521 と表示されます。

しかし、コンピューター内部の計算上、これは R(および Exploratory)が数値を画面に表示する際に自動的に丸めているためで、コンピューター内部で保持されている実際の値は次のようになっています。

1520.9999999999998...

R はこの値を表示する際、有効桁数(通常 15 桁程度)で丸めるため、画面上では 1521 と見えます。

一方で、floor関数は画面に表示されている値ではなく、内部に保持されている実際の値に対して切り捨てを行います。そのため、floor関数を適用すると1520になります。

原因:浮動小数点数の精度問題

ここからはそもそも、なぜ、90,000 * 0.0169の結果がコンピューター内部の計算上1521にならないのかを紹介します。

0.0169 のような小数は、コンピューターの内部では2進数として表現されます。

しかし0.0169 は 2 進数では割り切れない数のため、内部ではわずかに小さい近似値として格納されます。

格納されている実際の値(イメージ):
0.0169 → 0.016899999999999999...

このわずかな誤差がfloor関数の適用時に表面化します。

解決策:先に整数化してから掛け算する

問題の根本は 料率(小数)をそのまま掛け算することにあります。

そこで、あらかじめ料率に大きな整数(例: 10億 = 1,000,000,000)をかけて整数に変換してから掛け算をして、同じ数字で割ることで、この浮動小数点の誤差は回避できます。

floor(数量 * (料率 * 1000000000)) / 1000000000

まとめ

数量 * 料率 を先に計算すると浮動小数点誤差が混入するため、料率を先に整数化することでこの誤差を根本から回避します。

floor(数量 * (料率 * 1000000000)) / 1000000000

なおご自身のデータで計算をされる際には、「数量」「料率」の部分を実際の列名に置き換えてご使用ください。

Export Chart Image
Output Format
PNG SVG
Background
Set background transparent
Size
Width (Pixel)
Height (Pixel)
Pixel Ratio