Double値の小数点以下の不要な記号を削除しようとしています。私はそれをこのようにやっています:
_DecimalFormat format = new DecimalFormat("#.#####");
value = Double.valueOf(format.format(41251.50000000012343));
_
しかし、このコードを実行すると、次のようにスローされます。
_Java.lang.NumberFormatException: For input string: "41251,5"
at Sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.Java:1224)
at Java.lang.Double.valueOf(Double.Java:447)
at ...
_
ご覧のとおり、Double.valueOf()
は_"11.1"
_のような文字列でうまく機能しますが、_"11,1"
_のような文字列では窒息します。これを回避するにはどうすればよいですか?次のようなよりエレガントな方法はありますか
_Double.valueOf(format.format(41251.50000000012343).replaceAll(",", "."));
_
DecimalFormat
クラスのデフォルトの小数点記号値をオーバーライドする方法はありますか?他に何か考えはありますか?
沿って
私のdouble値の小数点の後の不要な記号を取り除きます
あなたは実際にあなたが例えばに丸めたいという意味ですか?小数第5位?次に、
_value = Math.round(value*1e5)/1e5;
_
(もちろん、他の数字を本当に切り落としたい場合は、Math.floor(value*1e5)/1e5
もできます)
問題は、10進形式が値をローカライズされた文字列に変換することです。ロケールのデフォルトの小数点は「,
」であると思います。これは、フランス語のロケールまたは世界の他の地域でよく発生します。
基本的にあなたがする必要があるのは「。」でフォーマットされた日付を作成することです。 Double.valueOf
が読み取れるように区切り文字。コメントで示されているように、Double.valueOf
を使用する代わりに、同じ形式を使用して値を解析することもできます。
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
value = format.parse(format.format(41251.50000000012343));
書式設定文字列が小数点記号として.
を使用しているのに対し、例外が,
を要求しているという事実は、ロケールの問題を示しています。つまり、DecimalFormatは、Double.valueOfが期待するものとは異なるロケールを使用して数値をフォーマットしています。
一般に、特定のロケールに基づいてNumberFormat
を作成する必要があります。
Locale myLocale = ...;
NumberFormat f = NumberFormat.getInstance(myLocale);
DecimalFormat のJavaDocsから:
デフォルトのロケールを含む特定のロケールのNumberFormatを取得するには、getInstance()などのNumberFormatのファクトリメソッドの1つを呼び出します。 NumberFormatファクトリメソッドはDecimalFormat以外のサブクラスを返す可能性があるため、通常、DecimalFormatコンストラクタを直接呼び出さないでください。
ただし、 BalusCが指摘しているように 、doubleをStringとしてフォーマットしてから、Stringを解析してdoubleに戻そうとすると、コードの臭いがかなり悪くなります。固定精度の10進数(金額など)を期待しているが、doubleは浮動小数点数であるため、多くの値(0.1
など)を使用できないため、問題が発生していると思われます。ダブル/フロートとして正確に表現されます。この場合、固定精度の10進数を処理する正しい方法は、 BigDecimal
を使用することです。
Locale.getDefault()
を使用して、システムの小数点記号を取得します。これも設定できます。セパレーターは通常、数千のセパレーターとして使用されるため、同時に異なるセパレーターを使用する必要はありません。2.001.000,23<=> 2,001,000.23
本当の解決策は次のとおりです。正確にカウントする必要があるものには浮動小数点数を使用しないでください。
浮動小数点数は、ほとんどの場合、実際の値の近似値です。これらは、物理量(最高の精度)の測定と計算、および統計的アーティファクトに適しています。
浮動小数点を桁数に丸めることにだまされるのはコードの臭いです。それは無駄であり、コードがすべての場合に正しく機能することを本当に確信することはできません。
'_,
_'の代わりに '_.
_'の場合は、ロケールを変更する必要があります。
小数点以下の桁数については、setMaximumFractionDigits(int newValue)
を使用してください。
残りについては、 javadocを参照 。
ローカルでは、小数点以下の区切りとしてカンマ「、」を使用しているようです。「。」を取得するには小数点として、次のように宣言する必要があります。
DecimalFormat dFormat =new DecimalFormat("#.#", new DecimalFormatSymbols(Locale.ENGLISH));
これにいくらか関連していますが、質問への回答ではありません。doubleとfloatの代わりにBigDecimalに切り替えてみてください。私はそれらのタイプの比較で多くの問題を抱えていました、そして今私はBigDecimalで行くのは良いことです。
double
/Double
の内部表現をそのように変更することはできません。
(人間の)表現を変更したい場合は、String
のままにしてください。したがって、そのDouble#valueOf()
を離れて、プレゼンテーションでDecimalFormat#format()
のString
結果を使用します。それを使って計算をしたい場合は、Double
とDouble#valueOf()
を使用していつでも実際のDecimalFormat
に戻すことができます。
ちなみに、あなたの不満のとおり私は私のdouble値の小数点の後の不要な記号を取り除こうとしています、 あなたは浮動小数点数の内部を認識しています ?プレゼンテーション層でフォーマットされていないdoubleを使用しているようで、平均的なUIではDecimalFormat
を使用してDouble
。
私のコード関数:
private static double arrondi(double number){
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
symbols.setDecimalSeparator('.');
DecimalFormat format = new DecimalFormat("#.#####", symbols);
return Double.valueOf(format.format(number));
}