mursのColdFusionメモ

頭の中から抜け落ちていく情報をメモがわりに書き溜めていくブログです。

ColdFusionで小数点の誤差にはPrecisionEvaluateを使う

ColdFusion 2018から、変数作成時にデータ型が保持されるようになったが、計算式などに変数を代入すると自動でキャストされる。

例えば、下記のプログラムを実施すると

<cfset a=1>
<cfset b="2">
<cfset c=a+b>
<cfscript>
 for (key in Variables) {
   writeOutput("#key# = #Variables[key]#(#getMetadata(Variables[key])#) <br>");
 }
</cfscript>

ColdFusion 2016までは、変数 a も b も内部で文字列型で管理されていた。計算式を使用した c はDouble 型に変換されている。

A = 1(class java.lang.String)
B = 2(class java.lang.String)
C = 3(class java.lang.Double)

データ型が保持されるColdFusion 2021や2018では、変数 a は数字、b は文字列型で管理される。計算式を使用した c は変わらずDouble 型に変換されている。

A = 1(class java.lang.Integer)
B = 2(class java.lang.String)
C = 3(class java.lang.Double)

このように、ColdFusionでは引き続き処理に応じて必要な型に自動でキャストされるので、変数の型に意識することは少ないが、小数点を含む計算式では注意しないといけない場合がある。 例えば、一見して問題が無いような下記の計算でも、小数点の丸め誤差などで結果が異なってしまう場合がある。

<cfoutput>
    #1000001.234567-1000000#<br>
    #1000000.1234567-1000000#<br>
    #100 * 0.57##Int(100 * 0.57)#<br>
</cfoutput>

1.23456699995 // 1.234567 じゃない
0.123456700006 // 0.1234567 じゃない
57 と 56

普段あまり遭遇しないので意識しないことも多い。でも、ふとした時に引っかかってしまう場合がある。その時はこの関数を使うことを覚えておこう。

<cfoutput>
    #PrecisionEvaluate(1000001.234567-1000000)#<br>
    #PrecisionEvaluate(1000000.1234567-1000000)#<br>
    #PrecisionEvaluate(100 * 0.57)##Int(PrecisionEvaluate(100 * 0.57))#<br>
</cfoutput>

1.234567
0.1234567
57.00 と 57

その他・参考情報

PrecisionEvaluateを使用した結果が指数で表示された場合は、java.math.BigDecimalオブジェクトのtoPlainStringメソッドを使用すると良い

cfassociates.samuraiz.co.jp