java - अनावश्यक दशमलव 0 के बिना स्ट्रिंग में फ़्लोटिंग संख्याओं को अच्छी तरह से कैसे प्रारूपित करें?




string floating-point (15)

इसे प्राप्त करने के दो तरीके यहां दिए गए हैं। सबसे पहले, छोटा (और शायद बेहतर) तरीका:

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;
  }

एक 64-बिट डबल पूर्णांक +/- 2 53 बिल्कुल प्रतिनिधित्व कर सकता है

इस तथ्य को देखते हुए मैं अपने सभी प्रकार के लिए एक प्रकार के रूप में एक डबल प्रकार का उपयोग करना चुनता हूं, क्योंकि मेरा सबसे बड़ा पूर्णांक 32-बिट हस्ताक्षरित है।

लेकिन अब मुझे इन छद्म पूर्णांक प्रिंट करना है, लेकिन समस्या यह है कि वे वास्तविक युगल के साथ भी मिश्रित होते हैं।

तो मैं जावा में इन युगलों को अच्छी तरह से कैसे मुद्रित करूं?

मैंने 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

निश्चित रूप से मैं उन शून्यों को ट्रिम करने के लिए एक फ़ंक्शन लिख सकता हूं, लेकिन स्ट्रिंग मैनिपुलेशन के कारण यह बहुत अधिक प्रदर्शन हानि है। क्या मैं एक और प्रारूप कोड के साथ बेहतर कर सकता हूं?

संपादित करें

टॉम ई और जेरेमी एस के जवाब अस्वीकार्य हैं क्योंकि वे दोनों मनमाने ढंग से 2 दशमलव स्थानों पर जाते हैं। जवाब देने से पहले समस्या को समझें।

संपादित करें 2

कृपया ध्यान दें कि String.format(format, args...) लोकेल-निर्भर है (नीचे उत्तरों देखें)।


एक DecimalFormat उपयोग करें और setMinimumFractionDigits(0)


क्यों नहीं:

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

यह डबल द्वारा समर्थित चरम मूल्यों के साथ काम करना चाहिए। पैदावार:

0.12
12
12.144252
0

देर जवाब लेकिन ...

आपने कहा कि आप अपनी संख्या को डबल प्रकार के साथ स्टोर करना चुनते हैं । मुझे लगता है कि यह समस्या की जड़ हो सकती है क्योंकि यह आपको पूर्णांक को युगल में स्टोर करने के लिए मजबूर करती है (और इसलिए मूल्य की प्रकृति के बारे में प्रारंभिक जानकारी खोना)। Number वर्ग (डबल और इंटीजर दोनों के सुपरक्लस) के उदाहरणों में अपनी संख्याओं को संग्रहीत करने के बारे में क्या है और प्रत्येक संख्या के सही प्रारूप को निर्धारित करने के लिए बहुरूपता पर भरोसा करते हैं?

मुझे पता है कि यह आपके कोड के पूरे हिस्से को रिफैक्टर करने के लिए स्वीकार्य नहीं हो सकता है, लेकिन यह बिना अतिरिक्त कोड / कास्टिंग / पार्सिंग के वांछित आउटपुट का उत्पादन कर सकता है।

उदाहरण:

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

मुझे पता है कि यह वास्तव में पुराना धागा है .. लेकिन मुझे लगता है कि ऐसा करने का सबसे अच्छा तरीका नीचे जैसा है:

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 होगा। यदि आपको सभी दशमलव स्थानों की आवश्यकता है लेकिन पीछे की ओर शून्य नहीं है तो यह सबसे अच्छा काम करता है।


मेरी मशीन पर, निम्नलिखित कार्य जेसनडी के उत्तर द्वारा प्रदान किए गए फ़ंक्शन से लगभग 7 गुना तेज है, क्योंकि यह String.format से बचाता है:

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

मैंने एक DoubleFormatter को दोहरी मानों की एक बड़ी संख्या को कुशल / प्रस्तुत करने योग्य स्ट्रिंग में कुशलतापूर्वक रूपांतरित करने के लिए बनाया है:

double horribleNumber = 3598945.141658554548844; 
DoubleFormatter df = new DoubleFormatter(4,6); //4 = MaxInteger, 6 = MaxDecimal
String beautyDisplay = df.format(horribleNumber);
  • यदि वी का पूर्णांक भाग MaxInteger => वैज्ञानिक प्रारूप में प्रदर्शित V (1.2345e + 30) से अधिक है तो अन्यथा सामान्य प्रारूप 124.45678 में प्रदर्शित होता है।
  • MaxDecimal दशमलव अंकों की संख्या तय करें (बैंकर के गोलाकार के साथ ट्रिम करें)

यहां कोड:

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 फ़ंक्शंस का उपयोग किया था। यदि आप गुवा का उपयोग नहीं करते हैं, तो इसे स्वयं कोड करें:

/**
 * 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();
}

मैंने ये ढूंढ निकाला:

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

सरल एक लाइनर, अगर वास्तव में जरूरत है तो केवल int में रहता है


यह काम अच्छी तरह से किया जाएगा, मुझे पता है कि विषय पुराना है, लेकिन जब तक मैं इस तक नहीं आया तब तक मैं उसी मुद्दे से संघर्ष कर रहा था। मुझे आशा है कि किसी को यह उपयोगी लगेगा।

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

यहां एक उत्तर दिया गया है जो वास्तव में काम करता है (यहां विभिन्न उत्तरों का संयोजन)

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

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

यह स्ट्रिंग को पूंछ 0-एस ड्रॉप करने के लिए बना देगा।


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);
    }
}

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

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

टिप्पणियों की ओर इशारा करते हुए, यह मूल प्रश्न का सही उत्तर नहीं है।
उस ने कहा, यह अनावश्यक पिछला शून्य के बिना संख्याओं को प्रारूपित करने का एक बहुत ही उपयोगी तरीका है।


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 मुझे सोनार रिपोर्ट में उल्लंघन दे रहा था






double