PR

えっ、0.1+0.2が0.3じゃない!?Power Queryの小数点誤差とその対策

Power Query

Power Queryで0.1と0.2を足したら…0.3になるはずなのに、0.3じゃないって言われちゃいました…! これってバグですか?Power Query、壊れちゃったんですか?

うんうん、それね。バグじゃなくて“仕様”だね〜。小数点の計算にはちょっとした罠があるんだよ。

Power Query(パワークエリ)で数値を扱っていると、「見た目は合ってるのに、なぜか比較がFALSEになる…」そんな不思議な現象に出くわすことがあります。 特に小数点を含む計算では、意外な落とし穴が潜んでいるんです。

この記事では、Power Queryで起こる小数点の計算誤差について、実際の検証例を交えながらわかりやすく解説します。 さらに、誤差を防ぐための回避策や工夫も紹介しているので、実務でのトラブル防止にも役立ちますよ。

「なんでFALSEになるの?」とモヤモヤしたことがある方、ぜひ最後まで読んでみてください!

スポンサーリンク

小数点の計算を検証する

元データの構造をチェック!

まずは、検証に使う表を用意しました。

この表には「値1」と「値2」があり、それぞれの行であらかじめ計算された「計」もあります。ここでの「計」は、Power Queryで実際に計算した結果ではなく、元からデータとして持っている値です。

たとえば、1行目には「0.1 + 0.1 = 0.2」という結果が「計」に入っています。これは手動で入れた“正解”という感じですね。

次に、「値1」と「値2」をPower Queryで加算して「加算」列を作り、その結果が「計」列と一致するかどうかを「比較」列でチェックしてみます。

1.「加算」列を作る

まずは、「値1」「値2」「計」の各列を、計算できるようにテキスト型から10進数型に変換しておきます。

そのあと、「列の追加」→「標準」→「加算」と進めて、「値1 + 値2」の結果を新しい列「加算」として追加します。これで、Power Queryで実際に足し算した列ができました。

2.「比較」列で結果をチェック!

次は、「加算」列と「計」列がちゃんと一致してるかどうかを判定する「比較」列を作成します。

これはカスタム列の機能を使えば簡単にできます。以下の式を使えば、2つの値が一致しているかどうかを判定してくれます。

比較結果がこちら。

本来なら、「比較」列の結果は全部 TRUE(つまり一致)になるはずなんです。 でも実際に見てみると、なぜか一部が FALSE(正しくない) になってるんですよね…。

実は小数点の計算ってちょっと苦手なんです

これは、Power Query がデータを「2進数の浮動小数点」で扱っていることが原因です。

たとえば、0.1 + 0.2 を計算すると、本来は 0.3 になるはずですが、内部的には 0.30000000000000004 のような微妙にズレた値になってしまいます。見た目では「0.3」と表示されていても、裏側では完全には一致していないんですね。

そのため、「計」列に 0.3 が入っていても、「加算」列の 0.30000000000000004 とは一致せず、比較結果が FALSE になってしまいます。

同じように、0.1 + 0.7 の計算結果も、内部では 0.7999999999999999 という少し小さい値になっていて、0.8 とは一致しません。これも FALSE になる原因です。

このように、見た目は同じでも、内部的な計算誤差のせいで比較結果が意図と違ってしまうことがあります。

この「浮動小数点演算の誤差」は、Power Query や Excel だけでなく、ほとんどのプログラミング言語でも共通して起こる現象なんです。ちょっとした落とし穴ですね。

通貨型に変換すれば安心?…とは限りません

「通貨型(Currency)」は、一般的に誤差が出にくい型として知られています。 でも、「通貨型に変換してから計算すれば、もう誤差は出ない!」…というわけではないんです。

この原因は、Power Queryの計算処理に使われる「型」にあると考えられます。 「通貨型」に変換したつもりでも、実際の計算は浮動小数点型で行われてしまうということだと思います。

実際に、通貨型に変換してから計算してみても、やっぱり比較結果が FALSE になってしまいました。

見た目は通貨型でも、裏側では誤差が出やすい型で計算されている可能性があるということですね。 ちょっとややこしいですが、これを知っておくだけでもトラブル回避に役立ちます!

小数点の誤差を防ぐには?回避策をご紹介!

小数点の計算で起こる誤差を防ぐには、丸め処理誤差が出にくい計算方法を使うのがポイントです。 ここでは、Power Queryで誤差をうまく回避するための方法をご紹介します。

なお、計算の精度が重要な場合は、「値1」「値2」のデータ型を通貨型(Currency)にしておくのがやっぱり安心です。 通貨型は固定小数点で扱われるため、一般的に浮動小数点型よりも誤差が出にくいとされています。少しでも不安は取り除いておくのが良いでしょう。

1.丸め処理を入れて誤差を防ぐ(加算後に四捨五入)

計算結果を比較する前に、丸め処理(四捨五入)を挟むことで、誤差によるズレを防ぐことができます。 具体的には、「加算」列の値を小数点第1位で丸めてから比較する、という流れです。

手順はこんな感じです。

1.「変換」→「丸め」→「四捨五入」を選択

2.丸める桁数は「小数点第1位」に設定します

もし加算と丸めを一度に済ませたい場合は、カスタム列で次のような関数を使えばOKです。

この方法を使ったところ、比較結果はすべて TRUE になりました! つまり、誤差によるFALSE判定をうまく回避できたということですね。

Number.Round の丸め方は、デフォルトでは「銀行型丸め」と呼ばれるものです。 これは、0.5を偶数に丸めるというちょっと特殊なルール。

もし「普通の四捨五入(0.5は常に切り上げ)」をしたい場合は、丸めモードを明示的に指定しましょう。

2.decimal型(固定10進数型)で計算する

Power Query で使える算術演算関数(たとえば Value.AddValue.Divide)は、デフォルトでは Precision.Double(倍精度の浮動小数点型)で処理されます。このままだと、例の小数点誤差が出てしまうんですね。

そこで、Value.Add 関数に Precision.Decimal を指定すると、固定小数点(decimal型)で計算されるようになります。これにより、誤差が発生しなくなります。

カスタム列では、こんな感じで書きます。

この方法で計算したところ、比較結果はすべて TRUE になりました! つまり、誤差なく正しく一致したということです。

ただし注意点として、decimal型は小数点以下4桁までしか扱えません。 それ以上の桁数が必要な場合は、別の方法を検討する必要があります。

3.整数に変換してから計算する方法

もうひとつ確実な対策として、小数を整数に変換してから計算する方法があります。 具体的には、小数点を含む値を10倍や100倍して整数化し、計算後に必要に応じて元のスケールに戻すというやり方です。

こうすることで、すべての演算が整数で処理されるため、浮動小数点による誤差が発生しなくなります。

たとえば、「値1」「値2」「計」列の値をそれぞれ10倍して整数に変換し、加算と比較を整数で行います。 以下の式では、計算と比較を1ステップでまとめています。

この方法を使ったところ、比較結果はすべて TRUE になりました! つまり、誤差なく正しく一致したということですね。

ただし注意点として、計算結果は元のスケール(小数点の位置)とは異なるので、必要に応じて割り戻し(10で割るなど)をして調整しましょう。

状況に合わせて、うまく組み合わせよう

ここまで紹介した方法は、それぞれにメリットがあります。 なので、用途に応じて組み合わせて使うのがベストです。

特に、数値の精度が求められる計算では、データ型をしっかり見直すのが大切。 たとえば、Precision.Decimal を使ったり、「通貨型(Currency)」に変更することで、誤差の発生を減らすことができると思います。

まとめ

見えない誤差に注意しよう。

Power Queryで数値を扱うときは、見た目が合っていても、内部的にはズレていることがあるという点に注意が必要です。 特に小数点を含む計算では、思わぬ誤差が発生してトラブルとなることも…。

こうした誤差を防ぐには、丸め処理通貨型への変換Precision.Decimalの指定整数化しての演算など、いくつかの回避策があります。

それぞれの方法にはメリット・デメリットがありますが、まずは「計算誤差が起こりうる」という前提を理解しておくことが大切です。 そのうえで、用途に合った対策を選ぶことで、意図しない不具合をしっかり防ぐことができます。

ちょっとした工夫で、Power Queryの計算もグッと安心になりますよ!

なるほど…小数点って、見た目はおとなしいのに、意外と気まぐれなんですね…! よ〜し、今日から私は“誤差ハンター”になりますっ!

タイトルとURLをコピーしました