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


496

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

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

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

तो मैं जावा में इन डबल्स को अच्छी तरह से कैसे प्रिंट करूं?

मैंने कोशिश की है String.format("%f", value), जो करीब है, सिवाय इसके कि मुझे छोटे मूल्यों के लिए बहुत सारे अनुगामी शून्य मिलते हैं।

यहाँ का एक उदाहरण आउटपुट है %f

232.00000000
.१८०००००००००
1237875192.0
४.५८००००००००
0.00000000
1.23450000

मुझे क्या चाहिए:

232
0.18
1237875192
4.58
0
1.2345

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

संपादित करें

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

EDIT 2

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


यदि आप चाहते हैं कि सभी पूर्णांक हैं, तो लंबे समय तक उपयोग क्यों न करें? आपको 2 ^ 63-1 पर अधिक धमाकेदार, कोई अजीब प्रारूपण और बेहतर प्रदर्शन नहीं मिलता है।
बैसज़रो

14
क्योंकि कुछ मूल्य वास्तव में युगल हैं
प्योरोलॉजिकल

2
कुछ मामलों में जहां यह समस्या उत्पन्न हुई थी JDK 7 में एक बग तय किया गया था: stackoverflow.com/questions/7564525/…
Pyrolutic

जावा की तुलना में स्ट्रिंग रूपांतरण के लिए क्या यह सिर्फ मेरे लिए या जावास्क्रिप्ट 100% बेहतर है?
एंडी

System.out.println("YOUR STRING" + YOUR_DOUBLE_VARIABLE);
शायन अमानी

जवाबों:


399

यदि विचार पूर्णांक के रूप में संग्रहीत पूर्णांक को प्रिंट करने के लिए है जैसे कि वे पूर्णांक हैं, और अन्यथा न्यूनतम आवश्यक परिशुद्धता के साथ युगल प्रिंट करें:

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
jlh

26
ओपी ने स्पष्ट रूप से कहा कि वे नहीं चाहते थे कि आउटपुट स्वरूपित हो %f। उत्तर वर्णित स्थिति और वांछित आउटपुट के लिए विशिष्ट है। ओपी ने सुझाव दिया कि उनका अधिकतम मूल्य 32-बिट अहस्ताक्षरित int था, जिसका मतलब intथा कि मैं स्वीकार्य था (जावा में वास्तव में मौजूद नहीं था, और कोई अनुकरणीय समस्या नहीं थी), लेकिन स्थिति भिन्न intहोने longपर एक तुच्छ निर्धारण है।
जेसन

1
जहां सवाल में यह कहता है कि उसे ऐसा नहीं करना चाहिए?
जेसन

6
String.format("%s",d)??? अनावश्यक ओवरहेड के बारे में बात करें। का उपयोग करें Double.toString(d)। दूसरे के लिए भी Long.toString((long)d):।
एंड्रियास

15
समस्या यह है कि %sस्थानीय लोगों के साथ काम नहीं करता है। जर्मन में, हम एक के बजाय "," का उपयोग करते हैं। दशमलव संख्या में। जबकि String.format(Locale.GERMAN, "%f", 1.5)"1,500000" String.format(Locale.GERMAN, "%s", 1.5)देता है , "1.5" - एक "" के साथ देता है, जो जर्मन भाषा में गलत है। क्या "% s" का स्थानीय-निर्भर संस्करण भी है?
फेलिक्स एडलमैन

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

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


16
यहां एक महत्वपूर्ण बात यह है कि 1.1 को बिना किसी अनुगामी शून्य के "1.1" के रूप में ठीक से प्रारूपित किया जाएगा।
स्टीव पोमेरॉय

53
और यदि आप एक विशिष्ट संख्या में ट्रेलिंग ज़ीरो चाहते हैं (जैसे कि यदि आप धन राशि प्रिंट कर रहे हैं) तो आप '#' के बजाय '0' का उपयोग कर सकते हैं (यानी नया डेसीमलफोर्मेट ("0.00")। प्रारूप (राशि);) ओपी नहीं चाहता था, लेकिन संदर्भ के लिए उपयोगी हो सकता है।
टीजे एलिस

22
हां, प्रश्न के मूल लेखक के रूप में यह गलत जवाब है। मजेदार है कि कितने वोट हैं। इस समाधान के साथ समस्या यह है कि यह मनमाने ढंग से 2 दशमलव स्थानों के लिए गोल है।
18

11
@Mazyod क्योंकि आप हमेशा प्रारूप की तुलना में अधिक दशमलव के साथ एक फ्लोटिंग पॉइंटिंग में पास कर सकते हैं। वह लेखन कोड है जो अधिकांश समय काम करेगा लेकिन सभी किनारे मामलों को कवर नहीं करेगा।
पाइरोलॉजिकल

15
@Pyrolinary - IMHO, कई अपवोट हैं क्योंकि, यह आपके लिए गलत समाधान है, यह 99% + उन लोगों के लिए सही समाधान है जो इस प्रश्नोत्तर को पाते हैं: आमतौर पर, एक डबल के अंतिम कुछ अंक "शोर" होते हैं: कि उत्पादन अव्यवस्था, पठनीयता के साथ हस्तक्षेप। इसलिए प्रोग्रामर निर्धारित करता है कि आउटपुट को पढ़ने वाले व्यक्ति के लिए कितने अंक फायदेमंद हैं, और कई को निर्दिष्ट करता है। एक सामान्य स्थिति यह है कि छोटी गणित की त्रुटियां जमा हो जाती हैं, इसलिए मान 12.000000034 हो सकता है, लेकिन यह 12 के चक्कर लगाना पसंद करेगा, और कॉम्पैक्ट रूप से "12" प्रदर्शित करेगा। और "12.340000056" => "12.34"।
टूलमेकरसैट

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

13
यह सही है लेकिन हमेशा शून्य का निशान लगाता है भले ही कोई आंशिक हिस्सा न हो। String.Format (। "% 2f, 1.0005) 1.00 प्रिंट और नहीं 1. वहाँ आंशिक भाग मुद्रित करने के लिए नहीं है, तो यह मौजूद नहीं है के लिए किसी भी फॉर्मेट स्पेसिफायर है?
Emre Yazici

87
नीचे मतदान के बाद से सवाल सभी अनुगामी शून्य को छीनने के लिए कह रहा है और यह उत्तर हमेशा शून्य होने की परवाह किए बिना दो अस्थायी बिंदुओं को छोड़ देगा।
ज़ुल्क्सिया

DecimalFormat एक अच्छी चाल थी - हालाँकि मैंने अपनी स्थिति (गेम लेवल टाइमर) के लिए इस एक का उपयोग करना समाप्त कर दिया था क्योंकि अनुगामी शून्य बेहतर दिख रहा था।
तीमुथियुस ली रसेल

2
मुझे लगता है कि आप च के बजाय जी का उपयोग करके अनुगामी शून्य को सही ढंग से संभाल सकते हैं।
पीटर अज़ताई

3
मैंने इस समाधान का उपयोग "% .5f" के साथ उत्पादन प्रणाली में किया है, और यह वास्तव में बहुत खराब है, इसका उपयोग न करें ... क्योंकि इसने इसे मुद्रित किया: 5.12E-4 को 0.000512 के बजाय
11

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()या System.out.printlnया FloatingDecimal.toJavaFormatStringवैज्ञानिक अंकन का उपयोग करता है, तो डबल से भी कम समय 10 ^ -3 है या से अधिक या 10 ^ 7 के बराबर

    double myValue = 0.00000021d;
    String.format("%s", myvalue); //output: 2.1E-7
  • का उपयोग करके %f, डिफ़ॉल्ट दशमलव परिशुद्धता 6 है, अन्यथा आप इसे हार्डकोड कर सकते हैं लेकिन इसके परिणामस्वरूप अतिरिक्त शून्य जोड़े जाते हैं यदि आपके पास कम दशमलव है। उदाहरण :

    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); //output: 0.000000210000
  • का उपयोग करके setMaximumFractionDigits(0);या %.0fआप किसी भी दशमलव परिशुद्धता को हटाते हैं, जो पूर्णांक / दीर्घ के लिए ठीक है लेकिन दोहरे के लिए नहीं

    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

    अंग्रेजी लोकेल का उपयोग करना सुनिश्चित करता है कि आपको दशमलव विभाजक के लिए एक बिंदु मिलेगा, जहां भी आपका कार्यक्रम चलेगा

340 का उपयोग क्यों कर रहे हैं setMaximumFractionDigits?

दो कारण :

  • setMaximumFractionDigitsएक पूर्णांक को स्वीकार करता है लेकिन इसके कार्यान्वयन में अधिकतम अंक होते हैं, DecimalFormat.DOUBLE_FRACTION_DIGITSजिसकी अनुमति 340 के बराबर होती है
  • Double.MIN_VALUE = 4.9E-324 तो 340 अंकों के साथ आप अपने दोहरे और ढीले सटीक दौर को सुनिश्चित नहीं कर रहे हैं

यह पूर्णांकों के लिए काम नहीं करता है, उदाहरण के लिए "2" बन जाता है "2."
kap

धन्यवाद, मैंने 0इसके बजाय पैटर्न का उपयोग करके उत्तर निर्धारित किया है#.
जेबीई

आप निरंतर का उपयोग नहीं कर रहे हैं, DecimalFormat.DOUBLE_FRACTION_DIGITSलेकिन आप मूल्य 340 का उपयोग कर रहे हैं, जिसे आप तब दिखाने के लिए एक टिप्पणी प्रदान करते हैं कि यह बराबर है DecimalFormat.DOUBLE_FRACTION_DIGITS। सिर्फ स्थिरांक का उपयोग क्यों नहीं करते ???
मर्टन बोडेवेस

1
क्योंकि यह विशेषता सार्वजनिक नहीं है ... यह "पैकेज फ्रेंडली" है
JBE

4
धन्यवाद! वास्तव में, यह उत्तर एकमात्र ऐसा है जो वास्तव में प्रश्न में उल्लिखित सभी आवश्यकताओं से मेल खाता है - यह अनावश्यक शून्य नहीं दिखाता है, संख्याओं को गोल नहीं करता है और स्थानीय-निर्भर है। महान!
फेलिक्स एडलमन

26

क्यों नहीं:

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

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

0.12
12
12.144252
0

2
मुझे यह उत्तर पसंद है जिसके द्वारा हमें टाइप रूपांतरण करने की आवश्यकता नहीं है।
जेफ टी।

संक्षिप्त विवरण: "%s"मूल रूप से कॉल d.toString()करता है, लेकिन यह साथ intया साथ काम नहीं करता है d==null!
नेफ

24

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

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

1
हम्म, यह स्थानों को ध्यान में नहीं रखता है, लेकिन जेसन का नहीं है।
TWStStrrob


11

नव, मन कभी नहीं।

स्ट्रिंग हेरफेर के कारण प्रदर्शन हानि शून्य है।

और यहाँ अंत के बाद ट्रिम करने के लिए कोड है %f

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

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

7
मैं नीच हूं क्योंकि आपका समाधान जाने का सबसे अच्छा तरीका नहीं है। String.format पर एक नजर है। आपको इस प्रारूप में सही प्रारूप प्रकार का उपयोग करने की आवश्यकता है। मेरे उपरोक्त उत्तर को देखो।
jjnguy

6
मैंने मतदान किया क्योंकि मुझे वही समस्या हो रही है, और यहाँ कोई भी समस्या को समझ नहीं रहा है।
Obay

1
टॉम के पद में उल्लिखित दशमलवफल के रूप में डाउनवॉट किया गया है जो आप देख रहे थे। यह काफी प्रभावी ढंग से जीरो स्ट्रिप्स करता है।
स्टीव पोमेरॉय

4
ऊपर, शायद वह गोलाई के बिना शून्य को ट्रिम करना चाहता है? PS @PyrolICAL, निश्चित रूप से आप सिर्फ नंबर का उपयोग कर सकते हैं ।replaceAll ("; 0? $", ""); (बाद में ("।") में शामिल है)
रेहो लिंडके

1
ठीक है, तो आप दशमलव लक्ष्य के साथ मेरे उद्देश्य को कैसे प्राप्त कर पाएंगे?
6

8

A DecimalFormatऔर का प्रयोग करेंsetMinimumFractionDigits(0)


मैं जोड़ूंगा setMaximumFractionDigits(2)और setGroupingUsed(false)(ओपी इसका उल्लेख नहीं करता लेकिन उदाहरण से ऐसा लगता है कि इसकी आवश्यकता है)। इसके अलावा, इस मामले में इसके तुच्छ के बाद से एक छोटा परीक्षण मामला चोट नहीं करता है। फिर भी, जब से मुझे लगता है कि यह इसका सबसे सरल समाधान है, एक
अपवोट

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

1
मुझे लगता है कि मैं इसमें आपका अनुसरण करूंगा: D
एयरकॉड

5

कृपया ध्यान दें कि String.format(format, args...)यह स्थानीय-निर्भर है क्योंकि यह उपयोगकर्ता के डिफ़ॉल्ट लोकेल का उपयोग करके प्रारूप करता है, जो कि शायद कॉमा और यहां तक ​​कि 123 456,789 या 123,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...) विभिन्न देशों में ।

EDIT 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
आपको इसे स्वीकृत उत्तर के लिए एक टिप्पणी के रूप में जोड़ना चाहिए
पाइरोलॉजिकल

टिप्पणियां इस परिशिष्ट की लंबाई या प्रारूप की अनुमति नहीं देती हैं। चूंकि यह संभवतः उपयोगी जानकारी जोड़ता है, मुझे लगता है कि इसे हटाने की बजाय अनुमति दी जानी चाहिए।
टेरी जान कॉमेडी

5

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

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

यहाँ कोड है:

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/…
Pyrolative

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

आपको इसके बजाय दाईं ओर से पहले गैर-शून्य-अंक की खोज करनी चाहिए और फिर सबस्ट्रिंग का उपयोग करें (और यह भी सत्यापित करें कि स्ट्रिंग में "" निश्चित रूप से शामिल है)। इस तरह, आप रास्ते में कई अस्थायी तार बनाने में नहीं आएंगे।
एंड्रॉयड डेवलपर

3

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

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

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

उदाहरण:

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

जावास्क्रिप्ट को उसी तरह से बनाया गया था :)
प्योरोलॉजिकल ऑक्ट

क्या आप अपने बयान को थोड़ा और समझा सकते हैं? यह मेरे लिए बिल्कुल स्पष्ट नहीं है ... :)
स्पॉट

2

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

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

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


1
फेलिक्स एडलमैन ने जो कहीं और कहा, उसे दोहराते हुए: यह एक लोकेल-स्वतंत्र स्ट्रिंग बनाएगा, जो उपयोगकर्ता के लिए हमेशा उपयुक्त नहीं हो सकता है।
जेजे ब्राउन

उचित बिंदु, मेरे उपयोग के मामले के लिए यह एक मुद्दा नहीं था, मैं अभी पूरी तरह से निश्चित नहीं हूं, लेकिन मुझे लगता है कि कोई भी मूल्य के बजाय स्ट्रिंग (फॉर्म (वांटेड लोकेल के साथ) का उपयोग कर सकता है
केसर

2

समूहन, गोलाई, कोई अनावश्यक शून्य (डबल में) के साथ प्रारूप मूल्य।

नियम:

  1. अंत में कोई शून्य नहीं ( 2.0000 = 2; 1.0100000 = 1.01)
  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. रिटर्न 0( null/-0 = 0)
  5. जोड़ता है $( = $56/-$56)
  6. समूहीकरण ( 101101.02 = $101,101.02)

और ज्यादा उदाहरण:

-99.985 = -$99.99

10 = $10

10.00 = $10

20.01000089 = $20.01

कोटलिन में डबल (एंड्रॉइड में उपयोग किए जाने वाले कारण) के मज़ेदार विस्तार के रूप में लिखा गया है, लेकिन जावा में आसानी से परिवर्तित किया जा सकता है, क्योंकि जावा कक्षाओं का उपयोग किया गया था।

/**
 * 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 के बारे में क्या?
एलेक्स78191

1.23450000 => 1.23
अहमद Mihoub

0

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

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
कभी-कभी, जब आप चीजों को अधिक सरल बनाते हैं, तो पीछे का कोड अधिक जटिल और कम अनुकूलित होता है ... लेकिन हां, आप बहुत सारे एपीआई कार्यों में निर्मित का उपयोग कर सकते हैं ...
एंड्रॉइड डेवलपर

1
आपको सरल से शुरू करना चाहिए और एक बार जब आप निर्धारित कर लेते हैं कि आपके पास प्रदर्शन की समस्या है, तो और उसके बाद ही आपको अनुकूलन करना चाहिए। कोड मानव को बार-बार पढ़ने के लिए है। इसे तेजी से चलाना माध्यमिक है। मानक एपीआई का उपयोग न करने से जब भी संभव हो आप बग को लागू करने की अधिक संभावना रखते हैं और केवल भविष्य में इसे बदलना अधिक कठिन बना देता है।
21:02 बजे पाइरोलॉजिकल

3
मेरा तर्क है कि आप ऐसा कोड लिखेंगे जो किसी भी तेजी से नहीं होगा। JVM बहुत स्मार्ट है और आप वास्तव में यह नहीं जानते हैं कि जब तक आप इसे प्रोफाइल नहीं बनाते हैं, तब तक यह कितना तेज या धीमा है। प्रदर्शन की समस्याओं का पता लगाया जा सकता है और जब यह समस्या बन जाती है, तो इसे ठीक किया जा सकता है। आपको समय से पहले इसके लिए अनुकूलन नहीं करना चाहिए। लोगों को पढ़ने के लिए कोड लिखें, न कि आप कैसे कल्पना करते हैं कि मशीन इसे चलाने जा रही है। एक बार जब यह एक प्रदर्शन समस्या बन जाती है, तो एक प्रोफाइलर के साथ कोड को फिर से लिखना।
प्योरोलॉजिकल

2
किसी और ने कोड स्वरूपण में सुधार करने के लिए उत्तर को संपादित किया। मैं अनुमोदन के लिए कई दर्जन संपादनों की समीक्षा कर रहा था और यहाँ उनके संपादन को मंजूरी देने जा रहा था, लेकिन संपादन असंगत थे इसलिए उन्होंने इसे ठीक किया। मैंने टेक्स्ट स्निपेट्स के व्याकरण में भी सुधार किया।
स्टीव विनोस्की

1
मुझे समझ नहीं आ रहा है। यदि आपने कहा कि प्रारूपण से कोई फर्क नहीं पड़ता है, तो आपने इसे वापस बदलने के लिए समय क्यों दिया?
OrhanC1

0

कोटलिन के लिए आप एक्सटेंशन का उपयोग कर सकते हैं जैसे:

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

0

यहां एक और उत्तर दिया गया है जिसमें दशमलव को केवल IF करने का विकल्प है, यदि दशमलव शून्य नहीं था।

   /**
     * 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
आपने POINT को प्रतिस्थापित नहीं किया, उदाहरण के लिए, "100.0" को "100 में बदल दिया जाएगा।"
3

अगर (f == (int) f) उसका ख्याल रखता है।
मार्टिन क्लोसी

2
F = 9999999999.00 पर फेल
दाऊद इब्न करीम

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


2
DecimalFormat "#। ##" के प्रारूप के साथ अतिरिक्त 0 नहीं रखेंगे यदि वे आवश्यक नहीं हैं: System.out.println(new java.text.DecimalFormat("#.##").format(1.0005));प्रिंट होगा1
एलेक्सा जी

यही मेरा सवाल है। यदि कोई हो तो 0.0005 प्रदर्शित होने पर क्या होगा। आप इसे 2 दशमलव अंकों में बदल देंगे।
सेतु

ओपी पूछ रहा है कि डबल्स में संग्रहीत पूर्णांक मूल्यों को कैसे प्रिंट किया जाए :)
एलेक्सा जी

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

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


1
यह सवाल का एक अच्छा समाधान है, अगर वे केवल शून्य को गिराने में रुचि रखते थे, तो आप अपने कोड को एक अनुगामी दशमलव बिंदु को कैसे ट्रिम करेंगे? यानी "1."
बाकायारो

29
सावधान रहें, आपका समाधान 1000 को 1 में बदल देगा, जो गलत है।
एलेक्स जी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.