2016-10-06 13 views
0

CSVファイルから一部のデータを読み込みましたが、文字列値をさまざまなデータ型に解析するカスタムコードがあります。数字のために、私が使用します。Sparkでのdouble値の精度

val format = NumberFormat.getNumberInstance() 

DecimalFormatを返し、私は私の数値を取得することにparse関数を呼び出しています。 DecimalFormatには任意の精度がありますので、精度を失うことはありません。ただし、データがSpark DataFrameにプッシュされると、DoubleTypeを使用してデータが格納されます。この時点で、私はいくつかの精密な問題を見ることを期待していますが、私はそうではありません。私はCSVファイルに0.1,0.01,0.001、...、1e-11の値を入力しようとしましたが、Spark DataFrameに格納されている値を見ると、それらはすべて正確に表現されます(0.099999999のようにはなりません)。私は任意の精度を格納するdouble値を期待していないので、私はこの動作に驚いています。誰も私がここで魔法を理解するのを助けることができますか?

乾杯!

+0

私はちょうどその表現を推測します。ダブルが扱うことのできる限界に近いものを試してみてください。 –

+0

また、「ダブル」は、範囲内にある限り、値を表すのに適しています。この問題は、倍精度を使用して表される任意の精度の数値に対して操作を実行すると開始されます。 –

+0

ダブルスは、サポートされている範囲内の整数を正確に表しますが、整数の間のすべての10進値を表すわけではないと思いました。それが私が混乱していたものです。 – bbtus

答えて

0

おそらく2つの問題があります:Doubleがその仮数で表すことができる有効数字の数。その指数の範囲。

おおよそ、Doubleは約16桁の精度を持ち、指数は約10^-308から10^+ 308までの範囲をカバーすることができます。 (実際の制限は、ieee754形式で使用されるバイナリ表現によって設定されます)。

1e-11のような数値を格納しようとすると、仮数部で使用できる56ビットで正確に近似できます。精度の問題が発生するのは、互いに近接している2つの数値を減算したい場合です(少数の最下位ビットだけが異なるだけです)(その仮数部は、それらの指数が同じになるようにずらして配置されていると仮定します) 。

たとえば、(1e20 + 2) - (1e20 + 1)を試してみると、1を得ることを望みますが、実際にはゼロになります。これは、Doubleに必要な20(10進)桁を表すのに十分な精度がないためです。しかし、(1e100 + 2e90) - (1e100 + 1e90)はほぼ正確に1e90と計算されます。

関連する問題