Java kullanarak bilimsel gösterim olmadan bir çift değeri nasıl yazdırabilirim?


223

Üstel form olmadan Java'da bir çift değer yazdırmak istiyorum.

double dexp = 12345678;
System.out.println("dexp: "+dexp);

Bu E notasyonu gösterir: 1.2345678E7.

Bunu şöyle yazdırmasını istiyorum: 12345678

Bunu önlemenin en iyi yolu nedir?

Yanıtlar:


116

Sen kullanabilirsiniz printf()ile %f:

double dexp = 12345678;
System.out.printf("dexp: %f\n", dexp);

Bu yazdırılacaktır dexp: 12345678.000000. Kesirli kısmı istemiyorsanız,

System.out.printf("dexp: %.0f\n", dexp);

Bu, belgelerde açıklanan biçim belirleyici dilini kullanır .

toString()Orijinal kodunuzda kullanılan varsayılan biçim burada belirtilmiştir .


1
ama o dexp: 12345681.000000hangi yanlış değer gösterdi.Ve aslında sonradan böyle web sayfasında benim gibi görüntülemek istiyorum.Neyse 1.2345678E7ben hangi aracılığıyla herhangi bir çift gibi 12345678ve başka bir şekilde saklayabilirsiniz yine de var mı?
Despicable

1
@despicable: Cevabın eski, eksik versiyonuna bakıyor olabilirsiniz. Sayfayı yeniden yüklemeyi deneyin. Hakkında bir paragraf olmalı %.0f.
NPE

@despicable, dexp'yi bir int olarak saklayabilirsiniz, böylece her iki şekilde de kolayca kullanabilirsiniz
Justin

10
BT NUMARASI KAPALI TURLARI
şaşırtmak

6
%.0fsayıyı yuvarlar. Sondaki sıfırları atmanın bir yolu var mı?
NurShomik

239

Java bir çiftte E gösterimini önler:

Bir ikiliyi normal bir sayıya dönüştürmenin beş farklı yolu:

import java.math.BigDecimal;
import java.text.DecimalFormat;

public class Runner {
    public static void main(String[] args) {
        double myvalue = 0.00000021d;

        //Option 1 Print bare double.
        System.out.println(myvalue);

        //Option2, use decimalFormat.
        DecimalFormat df = new DecimalFormat("#");
        df.setMaximumFractionDigits(8);
        System.out.println(df.format(myvalue));

        //Option 3, use printf.
        System.out.printf("%.9f", myvalue);
        System.out.println();

        //Option 4, convert toBigDecimal and ask for toPlainString().
        System.out.print(new BigDecimal(myvalue).toPlainString());
        System.out.println();

        //Option 5, String.format 
        System.out.println(String.format("%.12f", myvalue));
    }
}

Bu program yazdırır:

2.1E-7
.00000021
0.000000210
0.000000210000000000000001085015324114868562332958390470594167709350585
0.000000210000

Bunların hepsi aynı değer.

Protip: Bu rastgele basamakların neden çift değerde belirli bir eşiğin ötesinde göründüğüyle ilgili kafanız karıştıysa, bu video açıklıyor: computerphile neden 0.1+ 0.2eşittir 0.30000000000001?

http://youtube.com/watch?v=PZRI1IfStY0


Cevap ve özellikle ipucu için çok teşekkürler .. Bu video karışıklığımı çözdü.
AnujDeo

98

Kısacası:

Sondaki sıfırlardan ve Yerel ayar sorunlarından kurtulmak istiyorsanız, şunu kullanmalısınız:

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

Açıklama:

Diğer cevaplar neden bana uymadı:

  • Double.toString()ya da System.out.printlnya da FloatingDecimal.toJavaFormatStringçift az 10 ^ -3 ise bilimsel semboller kullanan veya daha büyük ya da 10 ^ 7 eşit
  • Kullanarak %f, varsayılan ondalık duyarlık 6'dır, aksi takdirde sabit kodlayabilirsiniz, ancak daha az ondalık sayınız varsa ekstra sıfır eklenir. Misal:

    double myValue = 0.00000021d;
    String.format("%.12f", myvalue); // Output: 0.000000210000
  • Tamsayılar / uzun ürünler için iyi olan, ancak çift için değil, ondalık duyarlığı kullanarak setMaximumFractionDigits(0);veya %.0fkaldırırsanız:

    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 kullanarak yerel bağımlısınız. Fransızca yerel ayarında, ondalık ayırıcı virgüldür, nokta değildir:

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

    İNGİLİZCE yerel ayarını kullanmak, programınızın çalışacağı her yerde ondalık ayırıcı için bir nokta elde etmenizi sağlar.

Neden 340 kullanıyorsunuz setMaximumFractionDigits?

İki sebep:

  • setMaximumFractionDigitsbir tamsayı kabul eder, ancak uygulanması izin maksimum basamak DecimalFormat.DOUBLE_FRACTION_DIGITSolan 340 eşittir
  • Double.MIN_VALUE = 4.9E-324 340 basamakla çiftinizi yuvarlamayacağınızdan ve hassasiyetinizi kaybetmeyeceğinizden emin olabilirsiniz.

Ne görüşünüz taşımaktadır new BigDecimal(myvalue).toPlainString()sağlanan açıklamadan itibaren docs.oracle.com/javase/7/docs/api/java/math/... ), bu sayıların farklı türde verildiğinde bunu nasıl davranacağını hemen belli değil ama bilimsel gösterim ortadan yok .
Derek Mahar

4
new BigDecimal(0.00000021d).toPlainString()0.0000002100000000000000010850153241148685623329583904705941677093505859375beklediğiniz çıktı değil ...
JBE

Cevabınızı scala'da nasıl kullanacağınız hakkında bir fikriniz var mı? muhtemelen uygun bir ithalat meselesi ama ben burada yeniyim.
jangorecki

BigDecimal.valueOf(0.00000021d).toPlainString()iyi çalışıyor (bu yüzden BigDecimal'in String yapıcısını kullanır)
marco

27

İle deneyebilirsiniz DecimalFormat. Bu sınıfla sayılarınızı ayrıştırma konusunda çok esneksiniz.
Kullanmak istediğiniz deseni tam olarak ayarlayabilirsiniz.
Örneğin sizin durumunuzda:

double test = 12345678;
DecimalFormat df = new DecimalFormat("#");
df.setMaximumFractionDigits(0);
System.out.println(df.format(test)); //12345678

16

BigDecimal toPlainString () içeren başka bir çözüm var, ama bu kez javadoc önerilen String-constructor kullanarak:

bu yapıcı Float.toString ve Double.toString tarafından döndürülen değerlerle uyumludur. Bu genellikle bir şamandırayı veya ikiliyi bir BigDecimal'e dönüştürmenin tercih edilen yoludur, çünkü BigDecimal (çift) yapıcısının öngörülemezliğinden muzdarip değildir.

En kısa haliyle şöyle görünür:

return new BigDecimal(myDouble.toString()).stripTrailingZeros().toPlainString();

Java 8 öncesi bu, sıfır değerli Çiftler için "0.0" ile sonuçlanır, bu nedenle şunları eklemeniz gerekir:

if (myDouble.doubleValue() == 0)
    return "0";

NaN ve sonsuz değerlerin fazladan kontrol edilmesi gerekir.

Tüm bu düşüncelerin nihai sonucu:

public static String doubleToString(Double d) {
    if (d == null)
        return null;
    if (d.isNaN() || d.isInfinite())
        return d.toString();

    // Pre Java 8, a value of 0 would yield "0.0" below
    if (d.doubleValue() == 0)
        return "0";
    return new BigDecimal(d.toString()).stripTrailingZeros().toPlainString();
}

Bu aynı zamanda Float ile güzel çalışmak için kopyalanabilir / yapıştırılabilir.


2
Ben bir String çift değer dönüştürmek için sayısız şemaları okudum ve bu en iyisi: kısa, basit, yapılandırılabilir.
Paul

Harika bir çözüm, gerçekten çift değerleri String'e dönüştürmeme ve bilimsel gösterimden kaçınmama yardımcı oldu. Teşekkürler!
pleft

Neden d.doubleValue() == 0yerine d == 0?
Alexei Fando

Çünkü bu durumda daha çok sevdiğim otomatik kutulamayı önler, ancak elbette bu konuda farklı görüşler olabilir. Java 8 kullanıyorsanız (9 muhtemelen aynı olacaktır), bu 2 satırı tamamen bırakabilirsiniz.
Manuel

Java 9 ile denedim, bu 2 satır 9'da da bırakılabilir.
Manuel

8

Bu, numaranız bir tam sayı olduğu sürece çalışır:

double dnexp = 12345678;
System.out.println("dexp: " + (long)dexp);

Eğer çift değişken ondalık noktadan sonra kesinlik kazanırsa kesir.


4

Bazı çift değerlerini para birimine dönüştürmem gerekiyordu ve çözümlerin çoğunun iyi olduğunu gördüm, ama benim için değil.

DecimalFormatİşte yaptığım şeydir, sonunda benim için yoluydu:

   public String foo(double value) //Got here 6.743240136E7 or something..
    {
        DecimalFormat formatter;

        if(value - (int)value > 0.0)
            formatter = new DecimalFormat("0.00"); // Here you can also deal with rounding if you wish..
        else
            formatter = new DecimalFormat("0");

        return formatter.format(value);
    }

Gördüğünüz gibi, sayı doğalsa, 2E7 (vs.) yerine - 20000000 olsun - ondalık nokta olmadan.

Ve ondalıksa, yalnızca iki ondalık hane alırım.


4

Java / Kotlin derleyici, 9999999'dan (10 milyondan büyük veya ona eşit) daha büyük herhangi bir değeri bilimsel gösterime dönüştürür. Epsilion gösterimi .

Örn: 12345678, 1.2345678E7'ye dönüştürülür

Bilimsel gösterime otomatik dönüştürmeyi önlemek için bu kodu kullanın:

fun setTotalSalesValue(String total) {
        var valueWithoutEpsilon = total.toBigDecimal()
        /* Set the converted value to your android text view using setText() function */
        salesTextView.setText( valueWithoutEpsilon.toPlainString() )
    }

3

Aşağıdaki kod, verilen numaranın bilimsel gösterimde sunulup sunulmadığını tespit eder. Eğer öyleyse, normal sunumda maksimum '25' basamakla temsil edilir.

 static String convertFromScientificNotation(double number) {
    // Check if in scientific notation
    if (String.valueOf(number).toLowerCase().contains("e")) {
        System.out.println("The scientific notation number'"
                + number
                + "' detected, it will be converted to normal representation with 25 maximum fraction digits.");
        NumberFormat formatter = new DecimalFormat();
        formatter.setMaximumFractionDigits(25);
        return formatter.format(number);
    } else
        return String.valueOf(number);
}

2

Herkesin doğru fikri olduğunu düşünüyorum, ancak tüm cevaplar basit değildi. Bunun çok kullanışlı bir kod parçası olduğunu görebiliyorum. İşte neyin işe yarayacağına dair bir pasaj:

System.out.println(String.format("%.8f", EnterYourDoubleVariableHere));

".8"Eğer ondalık basamak sayısını ayarlamak nerede göstermek istiyorum olduğunu.

Eclipse kullanıyorum ve sorun olmadı.

Umarım bu yardımcı oldu. Herhangi bir geri bildirim için teşekkür ederiz!


1

Üretim kodumda "x + 20/50" gibi bir dize alan math.Eval () işlevine dize girdisi olarak kullandığımda da aynı sorunu yaşadım

Yüzlerce makaleye baktım ... Sonunda hız yüzünden buna gittim. Eval fonksiyonu sonunda tekrar kendi sayı biçimine dönüştürecekti ve math.Eval () diğer yöntemlerin geri döndüğü E-07'yi desteklemedi ve 5 dp'nin üzerindeki herhangi bir şey yine de uygulamam için çok fazla ayrıntıydı .

Bu, artık 1000'den fazla kullanıcısı olan bir uygulama için üretim kodunda kullanılıyor ...

double value = 0.0002111d;
String s = Double.toString(((int)(value * 100000.0d))/100000.0d); // Round to 5 dp

s display as:  0.00021

1

Bu bir teğet olabilir .... ama bir tamsayı (tamsayı olamayacak kadar büyük) bir sayısallaştırıcıya (JSON, vb.) Sayısal bir değer koymanız gerekiyorsa, muhtemelen "BigInterger"

Örnek: değer bir dizedir - 7515904334

Bunu bir Json mesajında ​​sayısal olarak göstermemiz gerekiyor: {"contact_phone": "800220-3333", "servicer_id": 7515904334, "servicer_name": "BAZI CORPORATION"}

Yazdıramıyoruz veya şunu alacağız: {"contact_phone": "800220-3333", "servicer_id": "7515904334", "servicer_name": "BAZI KURUMSAL"}

Düğüme bu şekilde değer eklemek istenen sonucu verir: BigInteger.valueOf (Long.parseLong (değer, 10))

Bunun gerçekten konuyla ilgili olduğundan emin değilim, ancak bu soruyu çözümümü ararken en çok etkilendiğim için, burada başkalarının yararı için paylaşacağımı, yalan söyleyen, kötü arama yapan olacağını düşündüm. : D


-1

A ile temsil edilen tamsayı değerleri için double, diğer çözümlerden çok daha hızlı olan bu kodu kullanabilirsiniz.

public static String doubleToString(final double d) {
    // check for integer, also see https://stackoverflow.com/a/9898613/868941 and
    // https://github.com/google/guava/blob/master/guava/src/com/google/common/math/DoubleMath.java
    if (isMathematicalInteger(d)) {
        return Long.toString((long)d);
    } else {
        // or use any of the solutions provided by others
        return Double.toString(d);
    }
}

// Java 8+
public static boolean isMathematicalInteger(final double d) {
    return StrictMath.rint(d) == d && Double.isFinite(d);
}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.