私が望むのは、doubleをハーフアップ方式で丸める文字列にdoubleを変換する方法です。つまり、丸める10進数が5の場合、常に前の数値に丸められます。これは、ほとんどの状況でほとんどの人が期待する丸めの標準的な方法です。
私はまた有効数字だけが表示されることを望みます - すなわち、後続のゼロがあってはいけません。
これを行う方法の1つはString.format
メソッドを使用することです。
String.format("%.5g%n", 0.912385);
以下を返します。
0.91239
これは素晴らしいことですが、重要でなくても常に小数点以下5桁の数字が表示されます。
String.format("%.5g%n", 0.912300);
以下を返します。
0.91230
別の方法はDecimalFormatter
を使うことです:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
以下を返します。
0.91238
しかし、ご覧のとおり、これは半偶数丸めを使用しています。前の桁が偶数であればそれは切り捨てられます。私が欲しいのはこれです:
0.912385 -> 0.91239
0.912300 -> 0.9123
Javaでこれを実現するための最善の方法は何ですか?
setRoundingMode
を使用し、 RoundingMode
を明示的に設定して問題を半偶数ラウンドで処理し、必要な出力にフォーマットパターンを使用します。
例:
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
Double d = n.doubleValue();
System.out.println(df.format(d));
}
出力を返します。
12
123.1235
0.23
0.1
2341234.2125
value
がdouble
であると仮定すると、次のことができます。
(double)Math.round(value * 100000d) / 100000d
5桁の精度です。ゼロの数は小数の数を示します。
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
あなたにBigDecimal
を与えるでしょう。文字列を取り出すには、そのBigDecimal
のtoString
メソッド、またはプレーンフォーマットの文字列の場合はJava 5+のtoPlainString
メソッドを呼び出すだけです。
サンプルプログラム
package trials;
import Java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {
int yourScale = 10;
System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
}
また使用することができます
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
末尾に0があることを確認するため。
他の人が指摘したように、正しい答えはDecimalFormat
かBigDecimal
のどちらかを使うことです。浮動小数点は小数点以下の桁数をhaveしていないので、最初の場所で特定の数に丸める/切り捨てることはできません。あなたは10進数で作業しなければなりません、そしてそれはそれら2つのクラスがすることです。
このスレッドのすべての回答に対する反例として、乗算とそれに続く切り捨てとそれに続く除算を推奨するStackOverflow(およびその他の場所)の至るところで、次のコードを投稿しています。次のコードが92%以上のケースで誤った出力を生成する理由を説明するのはこのテクニックの支持者には必須です。
public class RoundingCounterExample
{
static float roundOff(float x, int position)
{
float a = x;
double temp = Math.pow(10.0, position);
a *= temp;
a = Math.round(a);
return (a / (float)temp);
}
public static void main(String[] args)
{
float a = roundOff(0.0009434f,3);
System.out.println("a="+a+" (a % .001)="+(a % 0.001));
int count = 0, errors = 0;
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
int scale = 2;
double factor = Math.pow(10, scale);
d = Math.round(d * factor) / factor;
if ((d % 0.01) != 0.0)
{
System.out.println(d + " " + (d % 0.01));
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
}
このプログラムの出力:
10001 trials 9251 errors
編集: 以下のコメントに対処するために、モジュラス演算にBigDecimal
とnew MathContext(16)
を使用してテストループのモジュラス部分を次のように修正しました。
public static void main(String[] args)
{
int count = 0, errors = 0;
int scale = 2;
double factor = Math.pow(10, scale);
MathContext mc = new MathContext(16, RoundingMode.DOWN);
for (double x = 0.0; x < 1; x += 0.0001)
{
count++;
double d = x;
d = Math.round(d * factor) / factor;
BigDecimal bd = new BigDecimal(d, mc);
bd = bd.remainder(new BigDecimal("0.01"), mc);
if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
{
System.out.println(d + " " + bd);
errors++;
}
}
System.out.println(count + " trials " + errors + " errors");
}
結果:
10001 trials 4401 errors
あなたが持っているとします
double d = 9232.129394d;
BigDecimal
を使えます
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();
bigDecimalなしで
d = Math.round(d*100)/100.0d;
両方のソリューションでd == 9232.13
DecimalFormatクラスを使用できます。
double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal = Double.valueOf(newFormat.format(d));
RealのJava How-to posts このソリューションは、Java 1.6より前のバージョンと互換性があります。
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
@ Milhous:四捨五入のための10進数形式は優れています。
また使用することができます
DecimalFormat df = new DecimalFormat("#.00000"); df.format(0.912385);
末尾に0があることを確認するため。
このメソッドは、実際の数値の丸めメカニズムを視覚的にだけでなく処理時にも提供するのに非常に優れていると付け加えます。
仮定:あなたは丸めメカニズムをGUIプログラムに実装しなければなりません。結果出力の精度/精度を変更するには、単にキャレットの形式を変更します(つまり、括弧内)。そのため:
DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);
出力として返されます:0.912385
DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);
出力として返されます:0.91239
DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);
出力として返されます:0.9124
[編集:脱字記号の形式がそのような場合( "#0。############")で小数点以下の桁数を入力した場合も同様。 3.1415926、引数のために、DecimalFormatはゴミ(例えば末尾のゼロ)を生成せず、:_ 3.1415926
..を返します。確かに、開発者の好みには少し冗長ですが、処理中のメモリ使用量が少なくて済み、実装も非常に簡単です。]
したがって、本質的に、DecimalFormatの長所は、文字列の外観(丸め精度セットのレベル)を同時に処理できることです。 Ergo:1つのコード実装の代償から2つの利点が得られます。 ;)
あなたは次のユーティリティメソッドを使用することができます -
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
double interestedInZeroDPs = valueToRound * multipicationFactor;
return Math.round(interestedInZeroDPs) / multipicationFactor;
}
結果をStringにしたい場合は、次のようにします。
DecimalFormat#setRoundingMode() :
DecimalFormat df = new DecimalFormat("#.#####");
df.setRoundingMode(RoundingMode.HALF_UP);
String str1 = df.format(0.912385)); // 0.91239
String str2 = new BigDecimal(0.912385)
.setScale(5, BigDecimal.ROUND_HALF_UP)
.toString();
これは、結果としてdouble
が欲しい場合に使えるライブラリの提案です。 doubleはあなたが望むものを正確に表現できないかもしれないので、私はそれを文字列変換にはお勧めしません(例: here を参照)
簡潔な解決策:
public static double round(double value, int precision) {
int scale = (int) Math.pow(10, precision);
return (double) Math.round(value * scale) / scale;
}
https://stackoverflow.com/a/22186845/212950 これを提供してくれた jpdymondに感謝 も参照してください。
あなたはBigDecimalを使用することができます
BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);
参照してください: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/ /
これを試してください。org.Apache.commons.math3.util.Precision.round(double x、int scale)
参照してください: http://commons.Apache.org/proper/commons-math/apidocs/org/Apache/commons/math3/util/Precision.html
Apache Commons Mathematics Libraryのホームページは次のとおりです。 http://commons.Apache.org/proper/commons-math/index.html
このメソッドの内部実装は次のとおりです。
public static double round(double x, int scale) {
return round(x, scale, BigDecimal.ROUND_HALF_UP);
}
public static double round(double x, int scale, int roundingMethod) {
try {
return (new BigDecimal
(Double.toString(x))
.setScale(scale, roundingMethod))
.doubleValue();
} catch (NumberFormatException ex) {
if (Double.isInfinite(x)) {
return x;
} else {
return Double.NaN;
}
}
}
(出力だけでなく)計算に10進数が本当に必要な場合は、doubleのようなバイナリベースの浮動小数点形式を使用しないでください。
Use BigDecimal or any other decimal-based format.
計算にはBigDecimalを使用しますが、扱う数値のサイズに依存することに注意してください。私のほとんどの実装では、doubleまたはintegerからLongへの構文解析で、非常に大きな数の計算には十分であることがわかりました。
実際、私は最近###################という数のGUIで正確な表現(16進数の結果とは対照的に)を得るためにparsed-to-longを使った###############文字(例として)。
このテーマに関する完全な答えが見つからなかったので、これを適切に処理するクラスをまとめました。
使い方はとても簡単です :
(この例では、カスタムロケールを使用しています)
public static final int DECIMAL_PLACES = 2;
NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);
String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"
double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345
これがクラスです :
import Java.math.RoundingMode;
import Java.text.DecimalFormat;
import Java.text.DecimalFormatSymbols;
import Java.text.ParseException;
import Java.util.Locale;
public class NumberFormatter {
private static final String SYMBOL_INFINITE = "\u221e";
private static final char SYMBOL_MINUS = '-';
private static final char SYMBOL_ZERO = '0';
private static final int DECIMAL_LEADING_GROUPS = 10;
private static final int EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation
private DecimalFormat decimalFormat;
private DecimalFormat decimalFormatLong;
private DecimalFormat exponentialFormat;
private char groupSeparator;
public NumberFormatter(int decimalPlaces) {
configureDecimalPlaces(decimalPlaces);
}
public void configureDecimalPlaces(int decimalPlaces) {
if (decimalPlaces <= 0) {
throw new IllegalArgumentException("Invalid decimal places");
}
DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
separators.setMinusSign(SYMBOL_MINUS);
separators.setZeroDigit(SYMBOL_ZERO);
groupSeparator = separators.getGroupingSeparator();
StringBuilder decimal = new StringBuilder();
StringBuilder exponential = new StringBuilder("0.");
for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
}
for (int i = 0; i < decimalPlaces; i++) {
decimal.append("#");
exponential.append("0");
}
exponential.append("E0");
decimalFormat = new DecimalFormat(decimal.toString(), separators);
decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
exponentialFormat = new DecimalFormat(exponential.toString(), separators);
decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
}
public String format(double value) {
String result;
if (Double.isNaN(value)) {
result = "";
} else if (Double.isInfinite(value)) {
result = String.valueOf(SYMBOL_INFINITE);
} else {
double absValue = Math.abs(value);
if (absValue >= 1) {
if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
value = Math.floor(value);
result = exponentialFormat.format(value);
} else {
result = decimalFormat.format(value);
}
} else if (absValue < 1 && absValue > 0) {
if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
result = decimalFormat.format(value);
if (result.equalsIgnoreCase("0")) {
result = decimalFormatLong.format(value);
}
} else {
result = exponentialFormat.format(value);
}
} else {
result = "0";
}
}
return result;
}
public String formatWithoutGroupSeparators(double value) {
return removeGroupSeparators(format(value));
}
public double parse(String value, double defValue) {
try {
return decimalFormat.parse(value).doubleValue();
} catch (ParseException e) {
e.printStackTrace();
}
return defValue;
}
private String removeGroupSeparators(String number) {
return number.replace(String.valueOf(groupSeparator), "");
}
}
万が一誰かがまだこれを手助けする必要があります。この解決策は私にとっては完璧に機能します。
private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}
目的の出力を持つString
を返します。
これを実現するために、このフォーマッタを使うことができます。
DecimalFormat df = new DecimalFormat("#.00");
String resultado = df.format(valor)
または
DecimalFormat df = new DecimalFormat("0.00"); :
このメソッドを使用して、常に2つの小数を取得します。
private static String getTwoDecimals(double value){
DecimalFormat df = new DecimalFormat("0.00");
return df.format(value);
}
この値を定義します。
91.32
5.22
11.5
1.2
2.6
メソッドを使用すると、この結果が得られます。
91.32
5.22
11.50
1.20
2.60
DecimalFormat
を使用してdouble
をString
に変換する場合は、非常に簡単です。
DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;
return formatter.format(num);
必要な動作に応じて、選択可能なRoundingMode
列挙値がいくつかあります。
以下のコードスニペットは、n桁の表示方法を示しています。トリックは、変数ppを1に設定し、その後にn個のゼロを設定することです。以下の例では、変数pp値は5つのゼロを持つので、5桁が表示されます。
double pp = 10000;
double myVal = 22.268699999999967;
String needVal = "22.2687";
double i = (5.0/pp);
String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
ここに来たのは、数を四捨五入する方法について簡単な答えを求めているためです。これはそれを提供するための補足的な答えです。
最も一般的なケースはMath.round()
を使うことです。
Math.round(3.7) // 4
数値は最も近い整数に丸められます。 .5
値は切り上げられます。それ以外の丸め動作が必要な場合は、他の Math 関数のいずれかを使用できます。下記の比較を参照してください。
上記のように、これは最も近い整数に丸めます。 .5
の小数部は切り上げられます。このメソッドはint
を返します。
Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4
Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4
任意の10進値は次の整数に切り上げられます。それは ceil ingに行きます。このメソッドはdouble
を返します。
Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0
Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0
任意の10進値は次の整数に切り捨てられます。このメソッドはdouble
を返します。
Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0
Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0
これは、10進数値が最も近い整数に丸められる点でroundに似ています。ただし、round
とは異なり、.5
の値は偶数の整数に丸められます。このメソッドはdouble
を返します。
Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***
Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
私はDecimalFormat
---または代わりにBigDecimal
を使用するという選択された答えに同意します。
最初に 更新 を読んでください。
しかし、もしあなたが do double値を丸めてdouble
値の結果を得たいのであれば、上記のようにorg.Apache.commons.math3.util.Precision.round(..)
を使うことができます。実装はBigDecimal
を使います、遅く、ゴミを作ります。
Decimal4jライブラリのDoubleRounder
ユーティリティには、似ているが高速でゴミのない方法が用意されています。
double a = DoubleRounder.round(2.0/3.0, 3);
double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
double c = DoubleRounder.round(1000.0d, 17);
double d = DoubleRounder.round(90080070060.1d, 9);
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
出力します
0.667
0.666
1000.0
9.00800700601E10
https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility を参照してください。
免責事項 decimal4jプロジェクトに携わっています。
更新: @iaforekが指摘したようにDoubleRounderが直感に反する結果を返すことがあります。その理由は、数学的に正しい丸めを実行するためです。たとえば、DoubleRounder.round(256.025d, 2)
は256.02に切り捨てられます。これは、256.025dとして表されるdouble値は、有理値256.025よりいくらか小さいため、切り捨てられるためです。
注:
BigDecimal(double)
コンストラクタの動作と非常に似ています(ただし、文字列コンストラクタを使用するvalueOf(double)
とは異なります)。そのため、この記事で前述したすべてのことから、I DoubleRounder の使用はお勧めできません。
JDKが最小限のテクノロジを使用している場合これはJavaライブラリを使わない方法です。
double scale = 100000;
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
DecimalFormatは出力に最適な方法ですが、私はそれを好まない。 double値を返すので、私は常にこれを常に行います。それで私はそれを単に出力以上に使うことができます。
Math.round(selfEvaluate*100000d.0)/100000d.0;
OR
Math.round(selfEvaluate*100000d.0)*0.00000d1;
小数点以下の桁数が大きい場合は、代わりにBigDecimalを使用できます。とにかく.0
は重要です。それがなければ、0.33333d5の丸めは0.33333を返し、9桁しか許されません。 .0
のない2番目の関数は、0.30000の戻り値0.30000000000000004に問題があります。
String.format()とDecimalFormatはデフォルトのLocaleを使用して文字列を生成することに注意してください。そのため、整数部分と小数部分の間の区切り文字としてドットまたはコンマを使用してフォーマットされた数字を書くことができます。丸みを帯びた文字列が目的の形式になるようにするには、次のようにJava.text.NumberFormatを使用します。
Locale locale = Locale.ENGLISH;
NumberFormat nf = NumberFormat.getNumberInstance(locale);
// for trailing zeros:
nf.setMinimumFractionDigits(2);
// round to 2 digits:
nf.setMaximumFractionDigits(2);
System.out.println(nf.format(.99));
System.out.println(nf.format(123.567));
System.out.println(nf.format(123.0));
英語ロケールで印刷されます(ロケールに関係なく):0.99 123.57 123.00
例はFarendaから取られています - doubleをStringに正しく変換する方法 。
一般的に、四捨五入はスケーリングによって行われます。round(num / p) * p
/**
* MidpointRounding away from zero ('arithmetic' rounding)
* Uses a half-epsilon for correction. (This offsets IEEE-754
* half-to-even rounding that was applied at the Edge cases).
*/
double RoundCorrect(double num, int precision) {
double c = 0.5 * EPSILON * num;
// double p = Math.pow(10, precision); //slow
double p = 1; while (precision--> 0) p *= 10;
if (num < 0)
p *= -1;
return Math.round((num + c) * p) / p;
}
// testing Edge cases
RoundCorrect(1.005, 2); // 1.01 correct
RoundCorrect(2.175, 2); // 2.18 correct
RoundCorrect(5.015, 2); // 5.02 correct
RoundCorrect(-1.005, 2); // -1.01 correct
RoundCorrect(-2.175, 2); // -2.18 correct
RoundCorrect(-5.015, 2); // -5.02 correct
あなたが10進数の5またはn数を考慮するなら。この答えであなたの問題を解決することがあります。
double a = 123.00449;
double roundOff1 = Math.round(a*10000)/10000.00;
double roundOff2 = Math.round(roundOff1*1000)/1000.00;
double roundOff = Math.round(roundOff2*100)/100.00;
System.out.println("result:"+roundOff);
出力は次のようになります。 123.0 1
これはループと再帰関数で解くことができます。
ここに私の答えがあります:
double num = 4.898979485566356;
DecimalFormat df = new DecimalFormat("#.##");
time = Double.valueOf(df.format(num));
System.out.println(num); // 4.89
dp =小数点以下の桁数、 value は倍精度です。
double p = Math.pow(10d, dp);
double result = Math.round(value * p)/p;