Bagaimana cara mendapatkan bagian utuh dan pecahan dari double di JSP / Java?

104

Bagaimana cara mendapatkan bagian utuh dan pecahan dari double di JSP / Java? Jika nilainya 3.25 maka saya ingin mendapatkan fractional =.25,whole = 3

Bagaimana kita bisa melakukan ini di Jawa?

Vinayak Bevinakatti
sumber
4
Anda tampaknya memiliki gagasan yang tidak akurat tentang apa itu mantissa dan eksponen. Mereka bukan hanya "seluruh bagian" dan "bagian pecahan". Lihat en.wikipedia.org/wiki/Floating_point
Jon Skeet
Sebenarnya saya membaca sekitar 5 posting sebelum berkata 'hei .. itu tidak disebut eksponen'. Otak saya membuang kata-kata dan mulai memecahkan masalah .. kebiasaan buruk membaca hal-hal pemrograman telah memberi saya :)
Gishu
1
Juga harap susun ulang pertanyaan OP .. untuk anak cucu di antara alasan-alasan lain.
Gishu
1
Kedengarannya seperti masalah pekerjaan rumah yang mencurigakan.
Brian Knoblauch
ohh begitu. saya sudah bertanya-tanya bagaimana dia mendapatkan hasil yang begitu aneh
Johannes Schaub - litb

Jawaban:

102

http://www.java2s.com/Code/Java/Data-Type/Obtainingtheintegerandfractionalparts.htm

double num;
long iPart;
double fPart;

// Get user input
num = 2.3d;
iPart = (long) num;
fPart = num - iPart;
System.out.println("Integer part = " + iPart);
System.out.println("Fractional part = " + fPart);

Keluaran:

Integer part = 2
Fractional part = 0.2999999999999998
Gishu
sumber
61
Sebenarnya halaman ini adalah hit pertama pada pencarian google untuk "get fractional and whole part out from double java" =)
Chris
12
Sebenarnya jawaban ini salah, karena nilai yang lebih besar dari panjang dapat mewakili maka akan memberikan angka yang sangat besar pada bagian pecahannya. Jawaban Dan Vinton di bawah ini sesederhana itu dan selalu mengembalikan hasil yang benar.
arberg
2
jadi sebenarnya, ini tidak benar, seperti yang Anda lihat di output. masukannya adalah pecahan dari 3 dan keluarannya adalah 29999999 ... menggunakan BigDecimal daripada Double akan melakukan triknya
Alex
2
@Alex Tidak, inputnya adalah angka yang sangat dekat dengan 2.3, tapi pasti tidak 2.3. Dan tidak ada yang salah dengan hasilnya, kecuali jika Anda menginginkan lebih dari 10 digit yang valid. Yang Anda butuhkan hanyalah beberapa pembulatan di setiap keluaran (misalnya, format %.9f) yang biasanya tidak terlalu merepotkan BigDecimal. Satu-satunya masalah di sini adalah overflow.
maaartinus
1
Mengubah double menjadi int hampir selalu merupakan ide yang buruk. Karena misalnya untuk (long)1.0e100Anda akan mendapatkan 0. Seringkali Anda membutuhkan nilai ganda hanya "berlantai" yang ada floor(). Jika Anda ingin menggunakan bagian integral dan pecahan modf(). Sungguh, ini jawaban yang buruk.
mojuba
155
double value = 3.25;
double fractionalPart = value % 1;
double integralPart = value - fractionalPart;
Dan Vinton
sumber
12
Mengapa ini tidak disukai? Bekerja dengan baik, dan dengan pengeditan saya akan bekerja dengan nilai-nilai negatif juga.
HRJ
Bagian integer bisa => long longPart = (long) 3.25
jdurango
2
Tidak akan berhasil untuk neg. nilai-nilai. Yaitu -3,25% 1 = 0,75 bukan 0,25. Jadi integralPart akan menjadi -3,25 - 0,75 = -4.
WindRider
2
@WindRider, saya cek negatif .. dan berhasil .. namun untuk tempat desimal yang jumlahnya kecil, akan ada sedikit kesalahan. Ex. untuk -03.0025 mengembalikan -0.0024999999999999467 dan -3.0
justshams
5
Kebingungan di sini adalah karena beberapa bahasa, seperti Python, digunakan %untuk berarti modulo ( -3.25 % 1 == 0.75) dan lainnya, seperti Java, Fortran, C, dan C ++, digunakan %untuk mengartikan sisa ( -3.25 % 1 == -0.25). WindRider mungkin telah mengetikkannya ke dalam REPL Python untuk kepentingannya, tetapi jawaban itu menyesatkan karena pertanyaan ini tentang JVM.
Jim Pivarski
24

Karena pertanyaan berusia 1 tahun ini ditendang oleh seseorang yang mengoreksi subjek pertanyaan, dan pertanyaan ini telah diberi tag jsp, dan tidak ada orang di sini yang dapat memberikan jawaban yang ditargetkan JSP, inilah kontribusi saya yang ditargetkan untuk JSP.

Gunakan JSTL (cukup taruh jstl-1.2.jar di /WEB-INF/lib) fmt taglib. Ada <fmt:formatNumber>tag yang melakukan apa yang Anda inginkan dan dengan cara yang cukup mudah dengan bantuan maxFractionDigitsdan maxIntegerDigitsatribut.

Ini SSCCE , cukup copy'n'paste'n'run itu.

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<%
    // Just for quick prototyping. Don't do this in real! Use servlet/javabean.
    double d = 3.25;
    request.setAttribute("d", d);
%>

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 343584</title>
    </head>
    <body>
        <p>Whole: <fmt:formatNumber value="${d}" maxFractionDigits="0" />
        <p>Fraction: <fmt:formatNumber value="${d}" maxIntegerDigits="0" />
    </body>
</html>

Keluaran:

Seluruh: 3

Pecahan: .25

Itu dia. Tidak perlu memijatnya dengan bantuan kode Java mentah.

BalusC
sumber
8

Pertanyaan awal menanyakan eksponen dan mantissa, bukan pecahan dan seluruh bagian.

Untuk mendapatkan eksponen dan mantissa dari double, Anda dapat mengubahnya menjadi representasi IEEE 754 dan mengekstrak bit seperti ini:

long bits = Double.doubleToLongBits(3.25);

boolean isNegative = (bits & 0x8000000000000000L) != 0; 
long exponent      = (bits & 0x7ff0000000000000L) >> 52;
long mantissa      =  bits & 0x000fffffffffffffL;
Rasmus Faber
sumber
Bukankah bit pertama mantinssa secara implisit diatur ke 1, jadi mantissa harus (bits & 0x000fffffffffffffL) | 0x0010000000000000L?
agnul
Rasmus itu bukan keluaran ryt Output: eksponen 0 dan mantissa 2814749767106560 dan jika Anda memilih kami agnul mantissa adalah 0
Vinayak Bevinakatti
Rusak dengan 4 suara lebih :) Meskipun saya melihat apa yang kode coba lakukan dengan memisahkan nilai ganda pada sambungannya, kode tersebut tampaknya tidak menghasilkan nilai yang benar.
Gishu
@agnul: Saya pikir "mantissa" biasanya hanya mengacu pada nilai bit. Anda mungkin hanya mengubahnya menjadi signifikan dengan (kadang-kadang) prepending sedikit. Namun menurut Wikipedia, kata mantissa sekarang sudah tidak digunakan lagi dan diganti dengan "pecahan".
Rasmus Faber
5

Logika utama Anda harus terlebih dahulu menemukan berapa digit yang ada setelah koma desimal.
Kode ini berfungsi untuk nomor apa pun hingga 16 digit. Jika Anda menggunakan BigDecimal, Anda dapat menjalankannya hingga 18 digit. letakkan nilai input (nomor Anda) ke variabel "num", di sini sebagai contoh saya telah mengodekannya dengan keras.

double num, temp=0;
double frac,j=1;

num=1034.235;
// FOR THE FRACTION PART
do{
j=j*10;
temp= num*j;
}while((temp%10)!=0);       

j=j/10;
temp=(int)num;
frac=(num*j)-(temp*j);

System.out.println("Double number= "+num);      
System.out.println("Whole part= "+(int)num+" fraction part= "+(int)frac);
OnePunchMan
sumber
Sobat, ini adalah jawaban yang sangat rumit untuk masalah sederhana. Apakah Anda melihat jawaban yang diterima?
Abu
1
Sekarang orang yang melakukan down-vote (bukan saya btw), seharusnya menjelaskan kenapa ada down-vote. Itu tidak baik. Tetapi kita semua memiliki skor 1 di beberapa titik atau lainnya.
Abu
2
@Gray pertanyaannya adalah memisahkan 3,25 sebagai '3' dan '25', dan jawaban yang diterima tidak akan pernah memberikan '25', itu akan selalu memberikan '2599999999'
OnePunchMan
@Gray Saya tahu siapa yang downvote itu, itu adalah nama pria Eji (pengguna lama) yang mengejek setiap komentar, jawaban, dan pertanyaan saya yang saya posting di blog ini. Akhirnya saya komplain ke moderator.
OnePunchMan
2
Jawaban ini sangat berguna jika Anda menginginkan bagian pecahan sebagai bilangan bulat
Guilherme Campos Hazan
5

Mantissa dan eksponen dari bilangan floating point ganda IEEE adalah nilai yang sedemikian rupa

value = sign * (1 + mantissa) * pow(2, exponent)

jika mantissa berbentuk 0.101010101_base 2 (yaitu bit yang paling signifikan digeser menjadi setelah titik biner) dan eksponen disesuaikan untuk bias.

Sejak 1.6, java.lang.Math juga menyediakan metode langsung untuk mendapatkan eksponen yang tidak bias (disebut getExponent (double))

Namun, bilangan yang Anda minta adalah bagian integral dan pecahan dari bilangan tersebut, yang dapat diperoleh dengan menggunakan

integral = Math.floor(x)
fractional = x - Math.floor(x)

meskipun Anda mungkin ingin memperlakukan angka negatif secara berbeda (floor(-3.5) == -4.0) , tergantung mengapa Anda menginginkan kedua bagian tersebut.

Saya sangat menyarankan agar Anda tidak menyebut mantissa dan eksponen ini.

Pete Kirkham
sumber
4

Tidak tahu apakah ini lebih cepat tetapi saya menggunakan

float fp = ip % 1.0f;
QED
sumber
3

[Sunting: Pertanyaan awalnya menanyakan bagaimana mendapatkan mantissa dan eksponen.]

Di mana n adalah angka untuk mendapatkan mantissa / eksponen nyata:

exponent = int(log(n))
mantissa = n / 10^exponent

Atau, untuk mendapatkan jawaban yang Anda cari:

exponent = int(n)
mantissa = n - exponent

Ini sebenarnya bukan Java tetapi harus mudah dikonversi.

Stephen Darlington
sumber
3

Bagian bilangan bulat didapat dari pengecoran sederhana dan untuk pecahan - pemisahan string:

double value = 123.004567890

int integerPart = (int) value; // 123

int fractionPart = 
  Integer.valueOf(String.valueOf(value)
      .split(".")[1]); // 004567890

/**
* To control zeroes omitted from start after parsing.
*/
int decimals =
  String.valueOf(value)
      .split(".")[1].length(); // 9
Zon
sumber
1

Bagaimana jika nomor Anda adalah 2.39999999999999. Saya kira Anda ingin mendapatkan nilai desimal yang tepat. Kemudian gunakan BigDecimal:

Integer x,y,intPart;
BigDecimal bd,bdInt,bdDec;
bd = new BigDecimal("2.39999999999999");
intPart = bd.intValue();
bdInt = new BigDecimal(intPart);
bdDec = bd.subtract(bdInt);
System.out.println("Number : " + bd);
System.out.println("Whole number part : " + bdInt);
System.out.println("Decimal number part : " + bdDec);
roybraym
sumber
0

Karena fmt:formatNumbertag tidak selalu memberikan hasil yang benar, berikut adalah pendekatan khusus JSP lainnya: Ini hanya memformat angka sebagai string dan melakukan penghitungan lainnya pada string, karena itu lebih mudah dan tidak melibatkan floating point lebih lanjut aritmatika.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<%
  double[] numbers = { 0.0, 3.25, 3.75, 3.5, 2.5, -1.5, -2.5 };
  pageContext.setAttribute("numbers", numbers);
%>

<html>
  <body>
    <ul>
      <c:forEach var="n" items="${numbers}">
        <li>${n} = ${fn:substringBefore(n, ".")} + ${n - fn:substringBefore(n, ".")}</li>
      </c:forEach>
    </ul>
  </body>
</html>
Roland Illig
sumber
Coba saja semua angka dari contoh saya. fmt:formatNumbermembulatkan argumennya, yang tidak diinginkan dalam kasus ini.
Roland Illig
0

Banyak dari jawaban ini memiliki kesalahan pembulatan yang mengerikan karena mereka mentransmisikan angka dari satu jenis ke jenis lainnya. Bagaimana tentang:

double x=123.456;
double fractionalPart = x-Math.floor(x);
double wholePart = Math.floor(x);
benofben
sumber
@justshams Bagaimana dengan menggunakan Math.abs?
Stephan
0

Jawaban yang diterima tidak berfungsi dengan baik untuk bilangan negatif antara -0 dan -1.0 Berikan juga bagian pecahannya negatif.

Contoh: Untuk angka -0,35

kembali

Bagian bilangan bulat = 0 Bagian pecahan = -0.35

Jika Anda bekerja dengan koordinat GPS, lebih baik mendapatkan hasil dengan signum pada bagian integer sebagai:

Bagian bilangan bulat = -0 Bagian pecahan = 0.35

Angka-angka ini digunakan misalnya untuk koordinat GPS, dimana penting signum untuk posisi Lat atau Long

Usulkan kode:

    double num;
    double iPart;
    double fPart;

    // Get user input
    num = -0.35d;
    iPart = (long) num;
    //Correct numbers between -0.0 and -1.0
    iPart = (num<=-0.0000001 && num>-1.0)? -iPart : iPart ;
    fPart = Math.abs(num - iPart);
    System.out.println(String.format("Integer part = %01.0f",iPart));
    System.out.println(String.format("Fractional part = %01.04f",fPart));

Keluaran:

Integer part = -0
Fractional part = 0,3500
pengguna1817835
sumber
0

Sejak Java 8, Anda dapat menggunakan Math.floorDiv.

Ini mengembalikan nilai terbesar (terdekat dengan tak terhingga positif) intyang kurang dari atau sama dengan hasil bagi aljabar.

Beberapa contoh:

floorDiv(4, 3) == 1
floorDiv(-4, 3) == -2

Alternatifnya, /operator dapat digunakan:

(4 / 3) == 1
(-4 / 3) == -1

Referensi:

Stephan
sumber
0

Saya akan menggunakan BigDecimal untuk solusinya. Seperti ini:

    double value = 3.25;
    BigDecimal wholeValue = BigDecimal.valueOf(value).setScale(0, BigDecimal.ROUND_DOWN);
    double fractionalValue = value - wholeValue.doubleValue();
Endery
sumber
0
String value = "3.06";

if(!value.isEmpty()){
    if(value.contains(".")){    
        String block = value.substring(0,value.indexOf("."));
        System.out.println(block);
    }else{
        System.out.println(value);
    }
}
Mohamed Sabirulla
sumber
Jawaban ini telah ditandai sebagai kualitas rendah. Jika itu menjawab pertanyaan, pertimbangkan untuk menambahkan sedikit teks untuk menjelaskan cara kerjanya.
lmo
0
// target float point number
double d = 3.025;

// transfer the number to string
DecimalFormat df = new DecimalFormat();
df.setDecimalSeparatorAlwaysShown(false);
String format = df.format(d);

// split the number into two fragments
int dotIndex = format.indexOf(".");
int iPart = Integer.parseInt(format.substring(0, dotIndex)); // output: 3
double fPart = Double.parseDouble(format.substring(dotIndex)); // output: 0.025
w__
sumber
0

Oke, ini mungkin terlambat, tetapi menurut saya pendekatan terbaik dan lebih akurat adalah menggunakan BigDecimal

double d = 11.38;

BigDecimal bigD = BigDecimal.valueOf(d);
int intPart = bigD.intValue();
double fractionalPart = bigD.subtract(BigDecimal.valueOf(intPart)).doubleValue();

System.out.println(intPart); // 11
System.out.println(fractionalPart ); //0.38
Omar Elashry
sumber
Jika Anda memiliki ganda, itu memiliki ketidaktepatan float. Mengonversinya menjadi BigDecimal tidak akan mengembalikan ketepatannya secara ajaib.
Taschi
@Taschi saya pikir pertanyaannya adalah tentang memisahkan bagian int dan pecahan, bukan tentang mengembalikan presisi!
Omar Elashry
Omar, Anda secara khusus berbicara tentang pendekatan Anda yang "lebih akurat", yang menurut saya tidak benar. Jawaban Anda sepenuhnya dapat diterima tetapi kata-kata itu tampaknya menyesatkan bagi saya, itulah sebabnya saya mengomentarinya.
Taschi
@Taschi, saya mengatakan bahwa karena dalam banyak jawaban Anda kehilangan nilai ketika Anda mendapatkan output, misalnya input (5.03) output int = 5 , fractional = 0.0299999, kita berbicara tentang input dan output, Anda memberi nilai dan mendapatkan kembali nilai Anda tanpa kehilangan 0,001% darinya! dan ini akurat, tidak menyesatkan!
Omar Elashry
Iya. Anda kehilangan presisi saat menyimpan sesuatu sebagai dobel di tempat pertama. Pembulatan saat mengonversi ke BigDecimal juga kehilangan presisi. Kedua kehilangan presisi tersebut dapat saling meniadakan, tetapi itu tidak "memulihkan" presisi, karena pemulihan presisi secara matematis tidak mungkin. Anda tidak dapat menarik informasi begitu saja.
Taschi
-2
public class MyMain2 {
    public static void main(String[] args) {
        double myDub;
        myDub=1234.5678;
        long myLong;
        myLong=(int)myDub;
        myDub=(myDub%1)*10000;
        int myInt=(int)myDub;
        System.out.println(myLong + "\n" + myInt);
    }
}
Michael Myers
sumber
Ini hanya berfungsi jika bilangan tersebut memiliki tepat 4 tempat desimal. Tidak sebaliknya.
Marquis dari Lorne