2017-06-05 9 views
1

の小数点以下の桁数が3以下であることを確認する効果的な方法を見つけたいと思います。double値を持つ小数点以下の数を見つける効率的な方法

double num1 = 10.012; //True 
double num2 = 10.2211; //False 
double num2 = 10.2; //True 

現在、私は正規表現の分割とカウントインデックスを使用しています。以下のように。私はたくさんのこの 関数を呼び出すことになりますので、

String[] split = new Double(num).toString().split("\\.") 
split[0].length() //num of decimal places 

これを行うには、効率的か良い方法はありますか?

+0

ダブルは正確な表現ではないため、2.112は2.119999999になる可能性があるので、あなたはここで問題があると思います。 BigDoubleを使う方がいいですか? – vikingsteve

+1

ここで重要な違いは、「double」は、数学的に*(例えば)100万位の非ゼロ値を持つが、文字列に変換されたときの値を含むことは完全に可能です* しない。これは、IEEE-754倍精度バイナリ浮動小数点の喜びです。文字列表現から得られる桁数は、その値を隣接する表現可能な値と区別するために必要な数だけです。 –

+0

@vikingsteveそれは私が傾いているものですが、私の主な関心事は記憶にあります。どのように効率的なメモリがBidDoubleであるかのように –

答えて

2

doubleを文字列に変換する最終的な結果に同意する方法で情報を伝えるソリューションが必要な場合は、効率は実際には上がりません。基本的にstringとcheckに変換する必要があります。その結果、倍数は数学的に(例えば)数百の位に(例えば)0以外の値を含む値を含むことは完全に可能ですが、それは文字列に変換されたときには0になりません。これはIEEE-754倍精度バイナリ浮動小数点の喜びです。文字列表現から得られる桁数は、その値を隣接する表現可能な値から区別するために必要な数だけです。 the Double docsから:メートルまたはの小数部分のために印刷されなければならないどのように多くの桁

?小数部分を表現するための数字は少なくとも1桁でなければなりません。それ以外にも、引数の値をタイプdoubleの隣接値と一意に区別するために必要な桁数以上の数字が必要です。すなわち、xが、有限の非ゼロの引数dに対してこの方法によって生成された10進表現で表される正確な数学的値であるとします。 dは、xに最も近いdoubleの値でなければなりません。 2つのdouble値がXに等しく近い場合、または、その後Dは、そのうちの一つでなければならず、Dの仮数の最下位ビットは、0でなければなりません。少ないメモリのオーバーヘッドを持っている必要があり

private static boolean onlyThreePlaces(double v) { 
    double d = (double)((long)(v * 1000))/1000; 
    return d == v; 
} 

...:

しかし、あなたはそのことについて心配していないなら、とlongにあなたの価値の範囲を制限することは大丈夫です、あなたはこのような何かを行うことができます仮定String-around-tripよりもその方法とDouble.toString(double)の結果は、上記の理由のために、小数点以下の桁という点で一致しなかったときの時間のかなりの数が存在しなかった場合

しかし、私は驚かれることと思います。

質問にコメントで

(I値の範囲について尋ねられたとき)、あなたが言った:

正直なところ、私はよく分かりません。私は価格を扱っている。まず、0-200Kと仮定します。

doubleを財務値に使うのは、通常はお勧めできません。メモリの問題でBigDecimalを使用しない場合は、精度を選択し、値の範囲に応じてintまたはlongを使用してください。たとえば、ペニーの精度が必要な場合は、100を掛けた値を使用します(たとえば、2000はⓆ20[または使用している通貨で、私はquatloosにはusingを使用しています)。ペニーの数をペナルティの精度にする必要がある場合(質問に示されるように)、100000を掛けます(2000000はⓆ20など)。精度が必要な場合は、より大きな乗数を選択します。百ペソ(百万円)の百ペソに行く場合でも、longとすると、Ⓠ922,337,203,685からⓆ922,337,203,685の範囲になります。

これは、このチェックを容易にするという副次的な利点があります。ただ直線%です。乗数が10000000(1ペニーの100分の1)の場合、無効なものを識別するにはちょうどvalue % 10000 != 0です(有効なものを識別するためにvalue % 10000 == 0)。

long num1 = 100120000; // 10.012 => true 
         // 100120000 % 10000 is 0 = valid 
long num2 = 102211000; // 10.2211 => false 
         // 102211000 % 10000 is 1000 = invalid 
long num3 = 102000000; // 10.2  => true 
         // 102000000 % 10000 is 0 = valid 
+0

それは逆でしょうか?私が10000の倍数で長時間使うと、50.0411 500411となる。 500411%10000は411を与える。それは3つ以上のd.p.説明していただけますか?ヘルプの事前のおかげです。 –

+0

@ KalebBlue:申し訳ありませんが、私は不明でした。 'value%10000> 0'は、* in *が有効であることを意味します。私は上記で明らかにし、拡張しました。 :-) **そして、負の値を持つ可能性があるので '!='でなければなりません。 '-102211000%10000'は' 1000 'ではなく '-1000'です。申し訳ありません。 –

関連する問題