【Qlik】Round処理が正しく行われない問題の解決方法
Qlik Sense / Qlik Viewにおいて、Round関数を使用した際に意図しない
挙動が発生するケースがあります。
具体的には、小数点付きの値の末尾が「5」であるデータについて、
正しく四捨五入処理ができないという事象です。
本記事では、その事象と解決方法を記載していきます。
この記事がおすすめな人
💡 Qlik SenseのRound関数で、期待どおりの結果が得られなくて困っている人
問題の内容
小数点付きの値の末尾が「5」であるデータについて、
正しく四捨五入処理ができない場合があります。
下図の例ではある値である[Value]を、小数点第2位で四捨五入を行いました。
処理結果として、10.95 → 11.0 を期待していましたが、
通常のRound処理では10.9と切り捨てられています。
Qlikにおける数値データの保持形式
Qlikコミュニティサイトによれば、Qlik内部でのデータの持ち方に起因しているようです。
QlikView (および Qlik Sense) は、IEEE 754 64 ビット倍精度バイナリ浮動小数点形式を使用してすべての数値を保存します。 これは、数値を格納するために 64 ビットが使用されることを意味します。 符号に 1 ビット、指数に 11 ビット、数値自体に 52 ビットです。 52 ビットの数値は、約 15 桁の有効数字に対応します。 これは、QlikView が数値の正確性を維持しながら、最大 14 桁の整数を保存できることを意味します。 ただし、14 桁を超える整数は有効数字 14 桁に四捨五入されます。
整数以外の場合は、状況が若干異なります。 一部の分数は正確な形式で保存できます。 0.5 と 0.25 は、正確なバイナリ対応物があるためです。 しかし、 0.1 と 0.2については正確な形式で保存ができません。これらには正確なバイナリ対応物がないためです。
これらは QlikView や IEEE 754 のエラーではありません。 むしろ、これらは 2 進浮動小数点数の期待における誤差を表します。 一部の値は 2 進数として正確に表現できないため、丸め誤差が発生するだけです。これを回避する方法はありません。 まず、浮動小数点数を(乗算によって)整数に変換し(小数部分を残さない)、その後、それに応じて整数を四捨五入(または切り捨て)し、 最後に整数を(除算によって)浮動小数点に変換し直すこと以外にありません。
浮動小数点値は固定長です。 64 ビット環境では 17 桁の仮数部が許可されます。つまり、1.75 のような値は 1.7500000000000000 として格納されます。
浮動小数点値は、定義上、正確な値ではなく、格納された値は 10 進数の最後の桁で異なる場合があります。 たとえば、値 1.75 は上または下に丸められますが、それでも同じ 10 進数値を表します。
1.7500000000000001
1.7500000000000000
1.7499999999999999
最後の 10 進数の変化は、値が処理されているときにいつでも発生する可能性があります。 これには、値がロードおよび格納されるとき、および値の計算または変更が実行されるときを含みます。
問題の回避方法
問題の解決方法については、引用文中の下記処理を実行することになります。
💡 浮動小数点数を(乗算によって)整数に変換し(小数部分を残さない)、その後、それに応じて整数を四捨五入(または切り捨て)し、最後に整数を(除算によって)浮動小数点に変換し直すこと以外にありません。
具体的なスクリプトは下記です。
まず四捨五入したい値を整数になおし、その値にRound関数を実行した上で最後に除算を行い、小数点付きの値に変換し直します。
(乗算・除算の桁数は適宜変更してください。)
Round(Value*10 ,1,0) / 10
まとめ
以上がRound処理が正しく行われない問題の解決方法でした。
もし数値検証等を行って値が合わない場合など、1度試してみて下さい。
参考記事
- Decimal Values In Qlik Sense And QlikView - April 2019 and earlier
- Rounded numerical values sometimes get unexpected results