浮動小数点数を不必要な10進数の0なしで文字列にうまくフォーマットする方法は?


496

64ビットdoubleは、整数+/- 2 53を正確に表すことができます

この事実を考えると、私の最大の整数は符号なし32ビットなので、すべての型の単一型としてdouble型を使用することを選択します。

しかし、今、これらの疑似整数を出力する必要がありますが、問題は、それらも実際のdoubleと混在していることです。

では、これらのdoubleをJavaで適切に印刷するにはどうすればよいですか?

私はを試しましたがString.format("%f", value)、小さい値に対して多くの後続ゼロが得られることを除いて、これは近いです。

これはの出力例です %f

232.00000000
0.18000000000
1237875192.0
4.5800000000
0.00000000
1.23450000

私が欲しいのは:

232
0.18
1237875192
4.58
0
1.2345

確かに、これらのゼロをトリミングする関数を書くことはできますが、それは文字列操作によるパフォーマンスの大幅な低下です。別のフォーマットコードを使ってもっと上手くできますか?

編集

トムEとジェレミーSの回答は、どちらも任意に小数点第2位に四捨五入されるため、受け入れられません。答える前に問題を理解してください。

編集2

これString.format(format, args...)ロケールに依存することに注意してください(以下の回答を参照してください)。


整数だけが必要な場合は、longを使用してみませんか?2 ^ 63-1を使用すると、書式がぎこちなく、パフォーマンスが向上します。
basszero 2009年

14
一部の値は実際には2倍になるため
Pyrolistical 2009年

2
:この問題が発生した場合には、JDK 7で修正されたバグだったstackoverflow.com/questions/7564525/...
Pyrolistical

それは私だけですか、それともJavaScriptはJavaよりも数値から文字列への変換で100%優れていますか
アンディ

System.out.println("YOUR STRING" + YOUR_DOUBLE_VARIABLE);
Shayan Amani

回答:


399

それらが整数であるかのようにdoubleとして格納された整数を出力することを目的とする場合、それ以外の場合、必要な最小の精度でdoubleを出力します。

public static String fmt(double d)
{
    if(d == (long) d)
        return String.format("%d",(long)d);
    else
        return String.format("%s",d);
}

生成する:

232
0.18
1237875192
4.58
0
1.2345

そして、文字列操作に依存しません。


9
同意しました、これは悪い答えです、それを使用しないでください。double最大int値より大きいと機能しません。それでもlong膨大な数の場合は失敗します。さらに、大きな値の場合、文字列を指数形式、たとえば「1.0E10」で返しますが、これはおそらく質問者が望んでいないことです。これを修正する%f%sは、2番目のフォーマット文字列の代わりにを使用してください。
jlh 14

26
OPは、を使用してフォーマットされた出力を望まないことを明示的に述べました%f。答えは、説明されている状況と目的の出力に固有です。OPは、その最大値が32ビットの符号なし整数であることを示唆しましたが、これintは許容できる(実際にはJavaに符号なしが存在せず、問題のある例はありませんでした)とint考えましたlongが、状況が異なる場合、に変更するのは簡単な修正です。
JasonD 2014

1
問題のどこにそれをすべきではないと言っていますか?
JasonD 2014

6
String.format("%s",d)??? 不要なオーバーヘッドについて話します。を使用しDouble.toString(d)ます。他にも同じ:Long.toString((long)d)
Andreas

15
問題は、それ%sがロケールでは機能しないことです。ドイツ語では、「。」の代わりに「、」を使用します。10進数で。しばらくString.format(Locale.GERMAN, "%f", 1.5)戻って「1,500000」、String.format(Locale.GERMAN, "%s", 1.5)戻り「1.5」 -ドイツ語の偽であると、「」。「%s」のロケール依存バージョンもありますか?
Felix Edelmann

414
new DecimalFormat("#.##").format(1.199); //"1.2"

コメントで指摘されているように、これは元の質問に対する正しい答えではありません。
とはいえ、不要な後続ゼロなしで数値をフォーマットするための非常に便利な方法です。


16
ここでの重要な注意事項は、1.1が後続のゼロなしで「1.1」として適切にフォーマットされることです。
Steve Pomeroy、2011

53
また、特定の数の後続ゼロが必要な場合(たとえば、金額を印刷している場合)、「#」の代わりに「0」を使用できます(つまり、新しいDecimalFormat( "0.00")。format(amount);)これOPが欲しかったものではありませんが、参考として役立つかもしれません。
TJエリス

22
はい、質問の元の著者として、これは間違った答えです。おかしな票がいくつあるか。このソリューションの問題は、小数点以下2桁に任意に丸められることです。
Pyrolistical

11
@Mazyodは、フォーマットよりも小数点以下の数が多い浮動小数点を常に渡すことができるためです。これは、ほとんどの場合機能するが、すべてのエッジケースをカバーしないコードを記述しています。
Pyrolistical

15
@Pyrolistical-私見、多くの賛成投票があります。これはあなたにとって間違った解決策ですが、これはこのQ&Aを見つけた人の99%以上にとって正しい解決策です。通常、ダブルの最後の数桁は「ノイズ」です。出力が乱雑になり、読みやすさが低下します。したがって、プログラマーは、出力を読む人にとって有益な桁数を決定し、その桁数を指定します。一般的な状況は、小さな数学エラーが蓄積されているためです。そのため、値は12.000000034になる可能性がありますが、12に丸めて、「12」としてコンパクトに表示することをお勧めします。そして「12.340000056」=>「12.34」。
ToolmakerSteve

226
String.format("%.2f", value) ;

13
これは正しいですが、小数部がない場合でも常に後続ゼロを出力します。String.format( "%。2f、1.0005)は、1ではなく1.00を出力します。小数部が存在しない場合に、それを出力しないようにする形式指定子はありますか?
Emre Yazici

87
質問はすべての後続ゼロを削除することを求めているため、反対票が投じられました。この回答は、ゼロであっても常に2つの浮動小数点を残します。
Zulaxia、2011

DecimalFormatは素晴らしいトリックでした-末尾のゼロがより見栄えが良かったので、私の状況(ゲームレベルタイマー)にこれを使用することになりました。
ティモシー・リー・ラッセル

2
fの代わりにgを使用すると、末尾のゼロを正しく処理できると思います。
Peter Ajtai 2012年

3
"%.5f"を含む本番システムでこのソリューションを使用しましたが、本当に悪いので、使用しないでください。これは、次のように出力されたためです:0.000512の代わりに5.12E-4
恥ずかしい2014

87

要するに:

末尾のゼロとロケールの問題を取り除きたい場合は、以下を使用する必要があります。

double myValue = 0.00000021d;

DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(340); //340 = DecimalFormat.DOUBLE_FRACTION_DIGITS

System.out.println(df.format(myValue)); //output: 0.00000021

説明:

他の回答が私に合わなかった理由:

  • Double.toString()or System.out.printlnまたはFloatingDecimal.toJavaFormatStringdoubleが10 ^ -3未満または10 ^ 7以上の場合、科学表記法を使用

    double myValue = 0.00000021d;
    String.format("%s", myvalue); //output: 2.1E-7
  • を使用する%fと、デフォルトの10進精度は6になります。それ以外の場合はハードコーディングできますが、小数が少ない場合は余分なゼロが追加されます。例:

    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); //output: 0.000000210000
  • 使用しsetMaximumFractionDigits(0);たり%.0f、あなたの整数/ long型のためではなく、二重の罰金である任意の10進精度を、削除

    double myValue = 0.00000021d;
    System.out.println(String.format("%.0f", myvalue)); //output: 0
    DecimalFormat df = new DecimalFormat("0");
    System.out.println(df.format(myValue)); //output: 0
  • DecimalFormatを使用すると、ローカルに依存します。フランス語ロケールでは、小数点記号はポイントではなくコンマです。

    double myValue = 0.00000021d;
    DecimalFormat df = new DecimalFormat("0");
    df.setMaximumFractionDigits(340);
    System.out.println(df.format(myvalue));//output: 0,00000021

    ENGLISHロケールを使用すると、プログラムが実行される場所に関係なく、小数点のポイントを確実に取得できます。

なぜ340を使用するのsetMaximumFractionDigitsですか?

2つの理由:

  • setMaximumFractionDigits整数を受け入れますが、その実装には許可される最大桁数DecimalFormat.DOUBLE_FRACTION_DIGITSが340です
  • Double.MIN_VALUE = 4.9E-324 だから340桁であなたはあなたの倍精度とルーズ精度を丸めないことは確かです

これは整数では機能しません。たとえば、「2」は「2」になります。
2015

おかげで、0代わりにパターンを使用して答えを修正しました#.
JBE

定数を使用してDecimalFormat.DOUBLE_FRACTION_DIGITSいませんが、値340を使用しています。この値に、が等しいことを示すコメントを入力しDecimalFormat.DOUBLE_FRACTION_DIGITSます。なぜ定数を使用しないのですか?
Maarten Bodewes、2015年

1
この属性はパブリックではないため、「パッケージフレンドリー」
JBE、2015年

4
ありがとう!実際、この回答は、質問で言及されているすべての要件に実際に一致する唯一の回答です。不要なゼロは表示されず、数値を丸めず、ロケールに依存します。すごい!
Felix Edelmann

26

何故なの:

if (d % 1.0 != 0)
    return String.format("%s", d);
else
    return String.format("%.0f",d);

これは、Doubleでサポートされている極値で機能するはずです。収量:

0.12
12
12.144252
0

2
型変換を行う必要がないので、私はこの答えを好みます。
ジェフT.

短い説明:"%s"基本的に呼び出されますd.toString()が、それは動作しませんint場合やd==null
ネフ

24

私のマシンでは、次の関数はJasonDの回答で提供される関数よりも約7倍高速ですString.format

public static String prettyPrint(double d) {
  int i = (int) d;
  return d == i ? String.valueOf(i) : String.valueOf(d);
}

1
うーん、これはロケールを考慮していませんが、JasonDも考慮していません。
TWiStErRob 2016

22

私の2セント:

if(n % 1 == 0) {
    return String.format(Locale.US, "%.0f", n));
} else {
    return String.format(Locale.US, "%.1f", n));
}

2
または単にreturn String.format(Locale.US, (n % 1 == 0 ? "%.0f" : "%.1f"), n);
MC皇帝

23.00123 ==> 23.00
aswzen、

11

気にしないでください。

文字列操作によるパフォーマンスの低下はゼロです。

そして、これは後に終了をトリミングするコードです %f

private static String trimTrailingZeros(String number) {
    if(!number.contains(".")) {
        return number;
    }

    return number.replaceAll("\\.?0*$", "");
}

7
あなたの解決策が最善の方法ではないため、私は反対票を投じました。String.formatをご覧ください。正しいフォーマットタイプを使用する必要があります。この場合はfloatです。上記の私の答えを見てください。
jjnguy 2009

6
私は同じ問題を抱えているため投票しましたが、誰も問題を理解していないようです。
Obay

1
トムの投稿で述べられているDecimalFormatとしての反対投票は、まさにあなたが探していたものです。ゼロを非常に効果的に取り除きます。
Steve Pomeroy、2011

4
上記に、多分彼は丸めなしでゼロをトリミングしたいですか?PS @Pyrolistical、確かにあなたは単にnumber.replaceAll( "。?0 * $"、 "");を使用できます (もちろんcontains( "。")の後)
Rehno Lindeque '10

1
それでは、DecimalFormatで私の目的をどのように達成できますか?
Pyrolistical 2012年

8

使用するDecimalFormatと、setMinimumFractionDigits(0)


私は追加setMaximumFractionDigits(2)しますsetGroupingUsed(false)(OPはそれについて言及していませんが、例からは必須であるようです)。また、小さなテストケースは、このケースでは些細なものであるため、問題にはなりません。それでも、それが最も簡単な解決策だと思うので、
賛成票は賛成票です

6
if (d == Math.floor(d)) {
    return String.format("%.0f", d);
} else {
    return Double.toString(d);
}

1
私はこれであなたをフォローすると思います:D
aeracode

5

これString.format(format, args...)ロケール依存であることに注意してください。これは、ユーザーのデフォルトのロケールを使用してフォーマットするためです。つまり、おそらくコンマと、123 456,789123,456.789のようなスペースも含まれます。、期待どおりではない場合があります。

あなたは使うことを好むかもしれません String.format((Locale)null, format, args...)

例えば、

    double f = 123456.789d;
    System.out.println(String.format(Locale.FRANCE,"%f",f));
    System.out.println(String.format(Locale.GERMANY,"%f",f));
    System.out.println(String.format(Locale.US,"%f",f));

プリント

123456,789000
123456,789000
123456.789000

そしてこれは String.format(format, args...)、さまざまな国で行われるです。

編集OK、手続きについての議論があったので:

    res += stripFpZeroes(String.format((Locale) null, (nDigits!=0 ? "%."+nDigits+"f" : "%f"), value));
    ...

protected static String stripFpZeroes(String fpnumber) {
    int n = fpnumber.indexOf('.');
    if (n == -1) {
        return fpnumber;
    }
    if (n < 2) {
        n = 2;
    }
    String s = fpnumber;
    while (s.length() > n && s.endsWith("0")) {
        s = s.substring(0, s.length()-1);
    }
    return s;
}

1
承認された回答にコメントとしてこれを追加する必要があります
Pyrolistical

コメントでは、この補遺の長さや形式は許可されていません。役に立つかもしれない情報を追加するので、削除するのではなくそのまま許可するべきだと思います。
Terry Jan Reedy 2015年

5

私は、DoubleFormatter大量のdouble値を素敵な/提示可能な文字列に効率的に変換するためにを作成しました:

double horribleNumber = 3598945.141658554548844; 
DoubleFormatter df = new DoubleFormatter(4,6); //4 = MaxInteger, 6 = MaxDecimal
String beautyDisplay = df.format(horribleNumber);
  • Vの整数部分がMaxIntegerを超える場合=>科学者形式(1.2345e + 30)でVを表示します。それ以外の場合、通常の形式124.45678で表示します。
  • MaxDecimalが10進数の数を決定します(銀行員の丸めを使用してトリミング)

ここにコード:

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;

/**
 * Convert a double to a beautiful String (US-local):
 * 
 * double horribleNumber = 3598945.141658554548844; 
 * DoubleFormatter df = new DoubleFormatter(4,6);
 * String beautyDisplay = df.format(horribleNumber);
 * String beautyLabel = df.formatHtml(horribleNumber);
 * 
 * Manipulate 3 instances of NumberFormat to efficiently format a great number of double values.
 * (avoid to create an object NumberFormat each call of format()).
 * 
 * 3 instances of NumberFormat will be reused to format a value v:
 * 
 * if v < EXP_DOWN, uses nfBelow
 * if EXP_DOWN <= v <= EXP_UP, uses nfNormal
 * if EXP_UP < v, uses nfAbove
 * 
 * nfBelow, nfNormal and nfAbove will be generated base on the precision_ parameter.
 * 
 * @author: DUONG Phu-Hiep
 */
public class DoubleFormatter
{
    private static final double EXP_DOWN = 1.e-3;
    private double EXP_UP; // always = 10^maxInteger
    private int maxInteger_;
    private int maxFraction_;
    private NumberFormat nfBelow_; 
    private NumberFormat nfNormal_;
    private NumberFormat nfAbove_;

    private enum NumberFormatKind {Below, Normal, Above}

    public DoubleFormatter(int maxInteger, int maxFraction){
        setPrecision(maxInteger, maxFraction);
    }

    public void setPrecision(int maxInteger, int maxFraction){
        Preconditions.checkArgument(maxFraction>=0);
        Preconditions.checkArgument(maxInteger>0 && maxInteger<17);

        if (maxFraction == maxFraction_ && maxInteger_ == maxInteger) {
            return;
        }

        maxFraction_ = maxFraction;
        maxInteger_ = maxInteger;
        EXP_UP =  Math.pow(10, maxInteger);
        nfBelow_ = createNumberFormat(NumberFormatKind.Below);
        nfNormal_ = createNumberFormat(NumberFormatKind.Normal);
        nfAbove_ = createNumberFormat(NumberFormatKind.Above);
    }

    private NumberFormat createNumberFormat(NumberFormatKind kind) {
        final String sharpByPrecision = Strings.repeat("#", maxFraction_); //if you do not use Guava library, replace with createSharp(precision);
        NumberFormat f = NumberFormat.getInstance(Locale.US);

        //Apply banker's rounding:  this is the rounding mode that statistically minimizes cumulative error when applied repeatedly over a sequence of calculations
        f.setRoundingMode(RoundingMode.HALF_EVEN);

        if (f instanceof DecimalFormat) {
            DecimalFormat df = (DecimalFormat) f;
            DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();

            //set group separator to space instead of comma

            //dfs.setGroupingSeparator(' ');

            //set Exponent symbol to minus 'e' instead of 'E'
            if (kind == NumberFormatKind.Above) {
                dfs.setExponentSeparator("e+"); //force to display the positive sign in the exponent part
            } else {
                dfs.setExponentSeparator("e");
            }

            df.setDecimalFormatSymbols(dfs);

            //use exponent format if v is out side of [EXP_DOWN,EXP_UP]

            if (kind == NumberFormatKind.Normal) {
                if (maxFraction_ == 0) {
                    df.applyPattern("#,##0");
                } else {
                    df.applyPattern("#,##0."+sharpByPrecision);
                }
            } else {
                if (maxFraction_ == 0) {
                    df.applyPattern("0E0");
                } else {
                    df.applyPattern("0."+sharpByPrecision+"E0");
                }
            }
        }
        return f;
    } 

    public String format(double v) {
        if (Double.isNaN(v)) {
            return "-";
        }
        if (v==0) {
            return "0"; 
        }
        final double absv = Math.abs(v);

        if (absv<EXP_DOWN) {
            return nfBelow_.format(v);
        }

        if (absv>EXP_UP) {
            return nfAbove_.format(v);
        }

        return nfNormal_.format(v);
    }

    /**
     * format and higlight the important part (integer part & exponent part) 
     */
    public String formatHtml(double v) {
        if (Double.isNaN(v)) {
            return "-";
        }
        return htmlize(format(v));
    }

    /**
     * This is the base alogrithm: create a instance of NumberFormat for the value, then format it. It should
     * not be used to format a great numbers of value 
     * 
     * We will never use this methode, it is here only to understanding the Algo principal:
     * 
     * format v to string. precision_ is numbers of digits after decimal. 
     * if EXP_DOWN <= abs(v) <= EXP_UP, display the normal format: 124.45678
     * otherwise display scientist format with: 1.2345e+30 
     * 
     * pre-condition: precision >= 1
     */
    @Deprecated
    public String formatInefficient(double v) {

        final String sharpByPrecision = Strings.repeat("#", maxFraction_); //if you do not use Guava library, replace with createSharp(precision);

        final double absv = Math.abs(v);

        NumberFormat f = NumberFormat.getInstance(Locale.US);

        //Apply banker's rounding:  this is the rounding mode that statistically minimizes cumulative error when applied repeatedly over a sequence of calculations
        f.setRoundingMode(RoundingMode.HALF_EVEN);

        if (f instanceof DecimalFormat) {
            DecimalFormat df = (DecimalFormat) f;
            DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();

            //set group separator to space instead of comma

            dfs.setGroupingSeparator(' ');

            //set Exponent symbol to minus 'e' instead of 'E'

            if (absv>EXP_UP) {
                dfs.setExponentSeparator("e+"); //force to display the positive sign in the exponent part
            } else {
                dfs.setExponentSeparator("e");
            }
            df.setDecimalFormatSymbols(dfs);

            //use exponent format if v is out side of [EXP_DOWN,EXP_UP]

            if (absv<EXP_DOWN || absv>EXP_UP) {
                df.applyPattern("0."+sharpByPrecision+"E0");
            } else {
                df.applyPattern("#,##0."+sharpByPrecision);
            }
        }
        return f.format(v);
    }

    /**
     * Convert "3.1416e+12" to "<b>3</b>.1416e<b>+12</b>"
     * It is a html format of a number which highlight the integer and exponent part
     */
    private static String htmlize(String s) {
        StringBuilder resu = new StringBuilder("<b>");
        int p1 = s.indexOf('.');

        if (p1>0) {
            resu.append(s.substring(0, p1));
            resu.append("</b>");
        } else {
            p1 = 0;
        }

        int p2 = s.lastIndexOf('e');
        if (p2>0) {
            resu.append(s.substring(p1, p2));
            resu.append("<b>");
            resu.append(s.substring(p2, s.length()));
            resu.append("</b>");
        } else {
            resu.append(s.substring(p1, s.length()));
            if (p1==0){
                resu.append("</b>");
            }
        }
        return resu.toString();
    }
}

注:GUAVAライブラリの2つの関数を使用しました。GUAVAを使用しない場合は、自分でコーディングします。

/**
 * Equivalent to Strings.repeat("#", n) of the Guava library: 
 */
private static String createSharp(int n) {
    StringBuilder sb = new StringBuilder(); 
    for (int i=0;i<n;i++) {
        sb.append('#');
    }
    return sb.toString();
}

1
精度がわかっている場合は、BigDecimalを使用します。docs.oracle.com/javase/1.5.0/docs/api/java/math/…を
Pyrolistical

5

これは仕事をうまくやり遂げるだろう、私はトピックが古いことを知っています、しかし私がこれに来るまで私は同じ問題で苦労していました。私は誰かがそれが役に立つと思うことを望みます。

    public static String removeZero(double number) {
        DecimalFormat format = new DecimalFormat("#.###########");
        return format.format(number);
    }

5
new DecimalFormat("00.#").format(20.236)
//out =20.2

new DecimalFormat("00.#").format(2.236)
//out =02.2
  1. 最小桁数の場合は0
  2. #桁をレンダリングします

これは問題の解決策を提供するかもしれませんが、コミュニティが回答から利益を得る(そして学ぶ)ための簡単な説明を追加することをお
勧め

4
String s = String.valueof("your int variable");
while (g.endsWith("0") && g.contains(".")) {
    g = g.substring(0, g.length() - 1);
    if (g.endsWith("."))
    {
        g = g.substring(0, g.length() - 1);
    }
}

代わりに、右側からゼロ以外の最初の数字を検索してから、subStringを使用する必要があります(もちろん、文字列に「。」が含まれていることも確認してください)。この方法では、途中でそれほど多くの一時的な文字列を作成することはありません。
Android開発者

3

遅い答えですが...

あなたはあなたがあなたの数をダブルタイプで保存することを選ぶと言いました。整数を格納する必要があるため、これが問題の根本になる可能性があると思いますをdouble(したがって、値の性質に関する初期情報が失われる。Numberクラス(DoubleとIntegerの両方のスーパークラス)のインスタンスに数値を格納し、ポリモーフィズムに基づいて各数値の正しい形式を決定するのはどうですか?

そのため、コード全体をリファクタリングすることは受け入れられないかもしれませんが、追加のコード/キャスト/解析を行わなくても、目的の出力を生成できます。

例:

import java.util.ArrayList;
import java.util.List;

public class UseMixedNumbers {

    public static void main(String[] args) {
        List<Number> listNumbers = new ArrayList<Number>();

        listNumbers.add(232);
        listNumbers.add(0.18);
        listNumbers.add(1237875192);
        listNumbers.add(4.58);
        listNumbers.add(0);
        listNumbers.add(1.2345);

        for (Number number : listNumbers) {
            System.out.println(number);
        }
    }

}

次の出力が生成されます。

232
0.18
1237875192
4.58
0
1.2345

ちなみにjavascriptは同じ選択をしました:)
Pyrolistical

@Pyrolisticalあなたのステートメントをもう少し説明できますか?それは私にはあまり明確ではありません... :)
2015年

2

これは私が思いついたものです:

  private static String format(final double dbl) {
    return dbl % 1 != 0 ? String.valueOf(dbl) : String.valueOf((int) dbl);
  }

単純な1つのライナー、本当に必要な場合にのみintにキャストする


1
Felix Edelmannが他の場所で言ったことを繰り返す:これはロケールに依存しない文字列を作成しますが、これは常にユーザーに適しているとは限りません。
JJブラウン、

私のユースケースではこれは問題ではありませんでしたが、今のところ完全にはわかりませんが、valueOfの代わりにString.format(必要なロケールで)を使用できると思います
keisar

2

価格をグループ化、丸め、不要なゼロ(ダブル)なしでフォーマットします。

ルール:

  1. 最後にゼロなし(2.0000 = 2; 1.0100000 = 1.01
  2. ポイントの後の最大2桁(2.010 = 2.01; 0.20 = 0.2
  3. ポイントの後の2桁目以降の丸め(1.994 = 1.99; 1.995 = 2; 1.006 = 1.01; 0.0006 -> 0
  4. 返品0null/-0 = 0
  5. 追加$= $56/-$56
  6. グループ化(101101.02 = $101,101.02

その他の例:

-99.985 = -$99.99

10 = $10

10.00 = $10

20.01000089 = $20.01

Doubleの楽しい拡張としてAndroidで使用されているKotlinで記述されていますが、Javaに簡単に変換できるため、Javaクラスが使用されていました。

/**
 * 23.0 -> $23
 *
 * 23.1 -> $23.1
 *
 * 23.01 -> $23.01
 *
 * 23.99 -> $23.99
 *
 * 23.999 -> $24
 *
 * -0.0 -> $0
 *
 * -5.00 -> -$5
 *
 * -5.019 -> -$5.02
 */
fun Double?.formatUserAsSum(): String {
    return when {
        this == null || this == 0.0 -> "$0"
        this % 1 == 0.0 -> DecimalFormat("$#,##0;-$#,##0").format(this)
        else -> DecimalFormat("$#,##0.##;-$#,##0.##").format(this)
    }
}

使い方:

var yourDouble: Double? = -20.00
println(yourDouble.formatUserAsSum()) // will print -$20

yourDouble = null
println(yourDouble.formatUserAsSum()) // will print $0

DecimalFormatについてhttps : //docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html


1
public static String fmt(double d) {
    String val = Double.toString(d);
    String[] valArray = val.split("\\.");
    long valLong = 0;
    if(valArray.length == 2){
        valLong = Long.parseLong(valArray[1]);
    }
    if (valLong == 0)
        return String.format("%d", (long) d);
    else
        return String.format("%s", d);
}

私はこの原因を使用しなければならなかっd == (long)dたソナーレポートで私に違反を与えていました


1
float price = 4.30;
DecimalFormat format = new DecimalFormat("0.##"); // Choose the number of decimal places to work with in case they are different than zero and zero value will be removed
format.setRoundingMode(RoundingMode.DOWN); // choose your Rounding Mode
System.out.println(format.format(price));

これはいくつかのテストの結果です:

4.30     => 4.3
4.39     => 4.39  // Choose format.setRoundingMode(RoundingMode.UP) to get 4.4
4.000000 => 4
4        => 4

1.23450000はどうですか?
Alex78191

1.23450000 => 1.23
アーメドミホーブ

0

これを実現するには2つの方法があります。まず、より短い(そしておそらくより良い)方法:

public static String formatFloatToString(final float f)
  {
  final int i=(int)f;
  if(f==i)
    return Integer.toString(i);
  return Float.toString(f);
  }

そして、これはより長く、おそらくより悪い方法です:

public static String formatFloatToString(final float f)
  {
  final String s=Float.toString(f);
  int dotPos=-1;
  for(int i=0;i<s.length();++i)
    if(s.charAt(i)=='.')
      {
      dotPos=i;
      break;
      }
  if(dotPos==-1)
    return s;
  int end=dotPos;
  for(int i=dotPos+1;i<s.length();++i)
    {
    final char c=s.charAt(i);
    if(c!='0')
      end=i+1;
    }
  final String result=s.substring(0,end);
  return result;
  }

1
時には、物事をより単純にすると、背後のコードはより複雑になり、最適化されなくなります...しかし、はい、組み込みのAPI関数をたくさん使用できます...
android developer

1
単純なものから始めて、パフォーマンスの問題があると判断したら、最適化する必要があります。コードは人間が何度も何度も読むためのものです。高速で実行することは二次的です。可能な限り標準APIを使用しないことで、バグが発生する可能性が高くなり、将来の変更が困難になるだけです。
Pyrolistical 2013年

3
あなたがそのように書いたコードが速くなることはないと主張します。JVMは非常に賢く、実際にプロファイルを作成するまでは、どれほど高速か低速かがわかりません。パフォーマンスの問題は、問題が発生したときに検出して修正できます。時期尚早に最適化しないでください。マシンがそれを実行することを想像する方法ではなく、人々が読むためのコードを書きます。パフォーマンスの問題が発生したら、プロファイラーを使用してコードを書き換えます。
ピロリスティカル

2
他の誰かがコードのフォーマットを改善するために回答を編集しました。承認のために数十の編集内容を確認し、それらの編集内容をここで承認しようとしましたが、編集内容に一貫性がないため、修正しました。テキストスニペットの文法も改善しました。
Steve Vinoski、2015

1
分からない。書式設定は重要ではないと言ったのに、なぜそれを元に戻すために時間を費やしたのですか?
OrhanC1 2016年

0

Kotlinの場合、次のような拡張機能を使用できます。

fun Double.toPrettyString() =
    if(this - this.toLong() == 0.0)
        String.format("%d", this.toLong())
    else
        String.format("%s",this)

0

これは、小数がゼロでない場合にのみ小数を追加するオプションがある別の回答です。

   /**
     * Example: (isDecimalRequired = true)
     * d = 12345
     * returns 12,345.00
     *
     * d = 12345.12345
     * returns 12,345.12
     *
     * ==================================================
     * Example: (isDecimalRequired = false)
     * d = 12345
     * returns 12,345 (notice that there's no decimal since it's zero)
     *
     * d = 12345.12345
     * returns 12,345.12
     *
     * @param d float to format
     * @param zeroCount number decimal places
     * @param isDecimalRequired true if it will put decimal even zero,
     * false will remove the last decimal(s) if zero.
     */
    fun formatDecimal(d: Float? = 0f, zeroCount: Int, isDecimalRequired: Boolean = true): String {
        val zeros = StringBuilder()

        for (i in 0 until zeroCount) {
            zeros.append("0")
        }

        var pattern = "#,##0"

        if (zeros.isNotEmpty()) {
            pattern += ".$zeros"
        }

        val numberFormat = DecimalFormat(pattern)

        var formattedNumber = if (d != null) numberFormat.format(d) else "0"

        if (!isDecimalRequired) {
            for (i in formattedNumber.length downTo formattedNumber.length - zeroCount) {
                val number = formattedNumber[i - 1]

                if (number == '0' || number == '.') {
                    formattedNumber = formattedNumber.substring(0, formattedNumber.length - 1)
                } else {
                    break
                }
            }
        }

        return formattedNumber
    }

-1

これが実際に機能する答えです(ここではさまざまな答えの組み合わせ)

public static String removeTrailingZeros(double f)
{
    if(f == (int)f) {
        return String.format("%d", (int)f);
    }
    return String.format("%f", f).replaceAll("0*$", "");
}

1
ポイントを置き換えなかった場合、たとえば、「100.0」は「100」に変換されます。
VinceStyling 2013年

if(f ==(int)f)がそれを処理します。
Martin Klosi 2013

2
f = 9999999999.00で失敗
Dawood ibnカリーム

-4

私はこれが本当に古いスレッドであることを知っています。

public class Test {

    public static void main(String args[]){
        System.out.println(String.format("%s something",new Double(3.456)));
        System.out.println(String.format("%s something",new Double(3.456234523452)));
        System.out.println(String.format("%s something",new Double(3.45)));
        System.out.println(String.format("%s something",new Double(3)));
    }
}

出力:

3.456 something
3.456234523452 something
3.45 something
3.0 something

唯一の問題は、.0が削除されない最後の問題です。しかし、あなたがそれとともに生きることができるなら、これは最もうまくいきます。%.2fは、小数点以下2桁に丸めます。DecimalFormatも同様です。小数点以下すべてが必要で、末尾のゼロが不要な場合は、これが最適です。


2
「#。##」の形式のDecimalFormatは、不要な場合は余分な0を保持しません。System.out.println(new java.text.DecimalFormat("#.##").format(1.0005));印刷されます1
Aleks G

それが私のポイントです。もしあれば、0.0005を表示したい場合はどうすればよいでしょうか。小数点以下2桁に丸めます。
セトゥー

OPは、doubleに格納された整数値を出力する方法を尋ねています:)
Aleks G

-8
String s = "1.210000";
while (s.endsWith("0")){
    s = (s.substring(0, s.length() - 1));
}

これにより、文字列がテーリング0-sをドロップするようになります。


1
これは、問題の良い解決策です。もし彼らが末尾のゼロが削除されることにのみ関心があるなら、末尾の小数点もトリミングするようにコードをどのように変更しますか?つまり「1」。
bakoyaro、2011年

29
注意してください、あなたの解決策は1000を1に変換しますが、これは間違っています。
Aleks G 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.