ฉันจะรับชิ้นส่วนทั้งหมดและเศษส่วนจาก double ใน JSP / Java ได้อย่างไร


104

ฉันจะรับชิ้นส่วนทั้งหมดและเศษส่วนจาก double ใน JSP / Java ได้อย่างไร หากมีค่าเป็น 3.25 แล้วผมต้องการที่จะได้รับfractional =.25,whole = 3

เราจะทำสิ่งนี้ใน Java ได้อย่างไร?


4
ดูเหมือนคุณจะมีความคิดที่ไม่ถูกต้องว่าแมนทิสซาและเลขชี้กำลังคืออะไร ไม่ใช่แค่ "ส่วนทั้งหมด" และ "ส่วนที่เป็นเศษส่วน" ดูen.wikipedia.org/wiki/Floating_point
Jon Skeet

อันที่จริงฉันอ่านประมาณ 5 โพสต์ก่อนที่จะไป 'เฮ้ .. นั่นไม่ได้เรียกว่าเลขชี้กำลัง' สมองของฉันพ่นคำออกมาและเริ่มแก้ปัญหา .. นิสัยที่ไม่ดีในการอ่านโปรแกรมเขียนโปรแกรมทำให้ฉัน :)
Gishu

1
นอกจากนี้โปรดเปลี่ยนข้อความคำถาม OP .. สำหรับลูกหลานด้วยเหตุผลอื่น ๆ
Gishu

1
ฟังดูน่าสงสัยเหมือนปัญหาการบ้าน
Brian Knoblauch

โอ้ฉันเห็น ฉันสงสัยอยู่แล้วว่าเขาได้ผลลัพธ์ที่แปลกประหลาดอย่างไร
Johannes Schaub - litb

คำตอบ:


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

ผลลัพธ์:

Integer part = 2
Fractional part = 0.2999999999999998

61
อันที่จริงหน้านี้เป็น Hit แรกในการค้นหาของ Google สำหรับ "รับเศษส่วนและส่วนทั้งหมดออกจาก java คู่" =)
คริส

12
อันที่จริงคำตอบนี้ไม่ถูกต้องสำหรับค่าที่มากกว่า long สามารถแทนค่าได้จะให้ตัวเลขจำนวนมากในส่วนเศษส่วน คำตอบของ Dan Vinton ด้านล่างนั้นง่ายพอ ๆ กันและให้ผลลัพธ์ที่ถูกต้องเสมอ
arberg

2
จริงๆแล้วนี่ไม่ถูกต้องอย่างที่คุณเห็นในผลลัพธ์ อินพุตเป็นเศษส่วนของ 3 และเอาต์พุตคือ 29999999 ... การใช้ BigDecimal แทน Double จะทำเคล็ดลับ
Alex

2
@ Alex ไม่มีการป้อนข้อมูลที่เป็นตัวเลขซึ่งเป็นมากใกล้กับแต่แน่นอนไม่ได้2.3 2.3และไม่มีอะไรผิดปกติกับผลลัพธ์เว้นแต่คุณต้องการตัวเลขที่ถูกต้องมากกว่า 10 หลัก ทั้งหมดที่คุณต้องมีการปัดเศษบางอย่างในแต่ละเอาท์พุท (เช่นรูปแบบ%.9f) BigDecimalซึ่งเป็นอาการปวดมักจะน้อยกว่า ปัญหาเดียวที่นี่คือล้น
maaartinus

1
การแปลง double เป็น int มักจะเป็นความคิดที่ไม่ดี เพราะเช่นสำหรับ(long)1.0e100คุณจะได้รับ 0. หลายครั้งที่คุณต้องการค่า double เพียงแค่ "ปูพื้น" floor()ซึ่งมี modf()หากคุณต้องการทั้งหนึ่งและส่วนชิ้นส่วนที่ใช้ จริงๆนี่เป็นคำตอบที่ไม่ดี
mojuba

156
double value = 3.25;
double fractionalPart = value % 1;
double integralPart = value - fractionalPart;

12
เหตุใดจึงลดลง ใช้งานได้ดีและการแก้ไขของฉันจะทำงานกับค่าลบเช่นกัน
HRJ

ส่วนจำนวนเต็มอาจเป็น => long longPart = (long) 3.25
jdurango

2
จะไม่ทำงานสำหรับ Neg ค่า ได้แก่ -3.25% 1 = 0.75 ไม่ใช่ 0.25. ดังนั้น integralPart จะเป็น -3.25 - 0.75 = -4
WindRider

2
@WindRider ฉันตรวจสอบค่าลบ .. และใช้งานได้ .. อย่างไรก็ตามสำหรับตำแหน่งทศนิยมที่มีจำนวนน้อยจะมีข้อผิดพลาดเล็กน้อย เช่น สำหรับ -03.0025 ผลตอบแทน -0.0024999999999999467 และ -3.0
shams.haq

5
ความสับสนที่นี่เป็นเพราะบางภาษาเช่น Python ใช้%เพื่อหมายถึง modulo ( -3.25 % 1 == 0.75) และอื่น ๆ เช่น Java, Fortran, C และ C ++ ใช้%เพื่อหมายถึงส่วนที่เหลือ ( -3.25 % 1 == -0.25) WindRider อาจพิมพ์ลงใน Python REPL เพื่อความสะดวก แต่คำตอบนั้นทำให้เข้าใจผิดเพราะคำถามนี้เกี่ยวกับ JVM
Jim Pivarski

24

เนื่องจากคำถามอายุ 1 ปีนี้ถูกเตะโดยผู้ที่แก้ไขหัวข้อคำถามและคำถามนี้ถูกแท็กjspและไม่มีใครสามารถให้คำตอบที่ตรงเป้าหมาย JSP ได้นี่คือการสนับสนุนที่กำหนดเป้าหมาย JSP ของฉัน

ใช้JSTL (เพียงแค่วางjstl-1.2.jarใน/WEB-INF/lib) fmt taglib มี<fmt:formatNumber>แท็กที่ทำในสิ่งที่คุณต้องการและในลักษณะที่ค่อนข้างง่ายด้วยความช่วยเหลือmaxFractionDigitsและmaxIntegerDigitsแอตทริบิวต์

นี่คือSSCCEเพียงแค่ copy'n'paste'n'run

<%@ 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>

เอาท์พุต:

ทั้งหมด: 3

เศษส่วน: .25

แค่นั้นแหละ. ไม่จำเป็นต้องนวดด้วยรหัส Java ดิบ


8

คำถามเดิมถามหาเลขชี้กำลังและแมนทิสซาแทนที่จะเป็นเศษส่วนและส่วนทั้งหมด

ในการรับเลขชี้กำลังและแมนทิสซาจากคู่คุณสามารถแปลงเป็นตัวแทนIEEE 754และแยกบิตดังนี้:

long bits = Double.doubleToLongBits(3.25);

boolean isNegative = (bits & 0x8000000000000000L) != 0; 
long exponent      = (bits & 0x7ff0000000000000L) >> 52;
long mantissa      =  bits & 0x000fffffffffffffL;

ไม่ใช่บิตแรกของ mantinssa โดยปริยายตั้งเป็น 1 ดังนั้น mantissa จึงควรเป็น (bits & 0x000fffffffffffffL) | 0x0010000000000000L?
agnul

Rasmus มันไม่ใช่เอาต์พุต ryt เอาต์พุต: เลขชี้กำลัง 0 และแมนทิสซา 2814749767106560 และถ้าคุณเลือก urs agnul mantissa คือ 0
Vinayak Bevinakatti

หักด้วยคะแนนโหวต 4 อัพ :) แม้ว่าฉันจะเห็นว่าโค้ดกำลังพยายามทำอะไรกับการแยกค่าสองเท่าที่ข้อต่อ แต่โค้ดดูเหมือนจะไม่ส่งออกค่าที่ถูกต้อง
Gishu

@agnul: ฉันคิดว่า "แมนทิสซา" มักจะหมายถึงค่าของบิต คุณอาจแปลงค่านี้เป็นค่านัยสำคัญโดย (บางครั้ง) ก่อนหน้า 1 บิต แต่ตามวิกิพีเดียปัจจุบันคำว่าแมนทิสซาเลิกใช้แล้วในความนิยมของ "เศษส่วน"
Rasmus Faber

5

ตรรกะหลักก่อนอื่นคุณต้องหาว่ามีกี่หลักหลังจากจุดทศนิยม
รหัสนี้ใช้ได้กับตัวเลขใด ๆ ไม่เกิน 16 หลัก หากคุณใช้ BigDecimal คุณสามารถเรียกใช้งานได้ไม่เกิน 18 หลัก ใส่ค่าอินพุต (หมายเลขของคุณ) ให้กับตัวแปร "num" นี่เป็นตัวอย่างที่ฉันได้เข้ารหัสไว้

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

เพื่อนนี่เป็นคำตอบที่ซับซ้อนมากสำหรับปัญหาง่ายๆ คุณลองดูคำตอบที่ได้รับการยอมรับหรือไม่?
สีเทา

1
ตอนนี้คนที่โหวตลง (ไม่ใช่ฉัน btw) น่าจะอธิบายได้ว่าทำไมถึงมีการโหวตลง นั่นไม่ดี แต่พวกเราทุกคนมีคะแนน 1 ในบางจุดหรืออื่น ๆ
สีเทา

2
@ สีเทาคำถามคือการแยก 3.25 เป็น '3' และ '25' และคำตอบที่ได้รับการยอมรับจะไม่เคยให้ '25' โดยจะให้ '2599999999' เสมอ
OnePunchMan

@ เกรย์ฉันรู้ว่าใครลงคะแนนมันเป็นผู้ชายชื่ออีจิ (ผู้ใช้เก่า) ล้อเลียนทุกความคิดเห็นคำตอบและคำถามของฉันที่ฉันโพสต์ในบล็อกนี้ ในที่สุดฉันก็บ่นกับผู้ดูแล
OnePunchMan

2
anwer นี้มีประโยชน์มากหากคุณต้องการให้ส่วนเศษส่วนเป็นจำนวนเต็ม
Guilherme Campos Hazan

5

แมนทิสซาและเลขชี้กำลังของเลขทศนิยมคู่ของ IEEE เป็นค่าดังกล่าว

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

ถ้าแมนทิสซาอยู่ในรูปแบบ 0.101010101_base 2 (นั่นคือบิตที่มีนัยสำคัญที่สุดจะถูกเลื่อนไปอยู่หลังจุดไบนารี) และเลขชี้กำลังจะถูกปรับสำหรับไบแอส

ตั้งแต่ 1.6 java.lang.Math ยังมีวิธีการโดยตรงในการรับเลขชี้กำลังที่เป็นกลาง (เรียกว่า getExponent (double))

อย่างไรก็ตามตัวเลขที่คุณขอเป็นส่วนหนึ่งและเศษส่วนของจำนวนซึ่งสามารถหาได้โดยใช้

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

แม้ว่าคุณอาจต้องการใช้จำนวนลบแตกต่างกัน(floor(-3.5) == -4.0)ขึ้นอยู่กับเหตุผลที่คุณต้องการทั้งสองส่วน

ผมขอแนะนำอย่างยิ่งว่าอย่าเรียกพวกแมนทิสซาและเลขชี้กำลัง


4

ไม่รู้ว่าเร็วกว่านี้ไหม แต่ฉันกำลังใช้

float fp = ip % 1.0f;

3

[แก้ไข: คำถามเดิมถามว่าจะรับแมนทิสซาและเลขชี้กำลังได้อย่างไร]

โดยที่nคือจำนวนที่จะได้แมนทิสซาจริง / เลขชี้กำลัง:

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

หรือเพื่อรับคำตอบที่คุณต้องการ:

exponent = int(n)
mantissa = n - exponent

สิ่งเหล่านี้ไม่ใช่ Java อย่างแน่นอน แต่ควรแปลงได้ง่าย


3

ส่วนจำนวนเต็มได้จากการหล่อแบบง่ายและสำหรับการแยกสตริงแบบเศษส่วน

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

1

จะเกิดอะไรขึ้นถ้าหมายเลขของคุณคือ 2.39999999999999 ฉันคิดว่าคุณต้องการได้ค่าทศนิยมแน่นอน จากนั้นใช้ 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);

0

เนื่องจากfmt:formatNumberแท็กไม่ได้ให้ผลลัพธ์ที่ถูกต้องเสมอไปนี่จึงเป็นอีกวิธีการเฉพาะของ JSP: เพียงแค่จัดรูปแบบตัวเลขเป็นสตริงและทำการคำนวณส่วนที่เหลือในสตริงเนื่องจากง่ายกว่าและไม่เกี่ยวข้องกับทศนิยมเพิ่มเติม เลขคณิต.

<%@ 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>

ลองใช้ตัวเลขทั้งหมดจากตัวอย่างของฉัน fmt:formatNumberปัดเศษอาร์กิวเมนต์ซึ่งไม่ต้องการในกรณีนี้
Roland Illig

0

คำตอบเหล่านี้จำนวนมากมีข้อผิดพลาดในการปัดเศษที่น่ากลัวเนื่องจากกำลังส่งตัวเลขจากประเภทหนึ่งไปยังอีกประเภทหนึ่ง เกี่ยวกับ:

double x=123.456;
double fractionalPart = x-Math.floor(x);
double wholePart = Math.floor(x);

@justshams ใช้แล้วMath.absไง?
Stephan

0

คำตอบที่ยอมรับใช้ไม่ได้ผลสำหรับจำนวนลบระหว่าง -0 ถึง -1.0 ให้ส่วนที่เป็นเศษส่วนเป็นลบด้วย

ตัวอย่างเช่น: สำหรับหมายเลข -0,35

ผลตอบแทน

ส่วนจำนวนเต็ม = 0 ส่วนเศษส่วน = -0.35

หากคุณกำลังทำงานกับพิกัด GPS จะเป็นการดีกว่าที่จะให้ผลลัพธ์กับเครื่องหมายในส่วนจำนวนเต็มเป็น:

ส่วนจำนวนเต็ม = -0 ส่วนเศษส่วน = 0.35

ตัวเลขเหล่านี้ใช้สำหรับพิกัด GPS ซึ่งเป็นสัญญาณสำคัญสำหรับตำแหน่ง Lat หรือ Long

เสนอรหัส:

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

เอาท์พุต:

Integer part = -0
Fractional part = 0,3500

0

ตั้งแต่ Java 8 คุณสามารถใช้ Math.floorDiv .

ส่งกลับค่าที่ใหญ่ที่สุด (ใกล้เคียงกับอินฟินิตี้บวกมากที่สุด) intที่น้อยกว่าหรือเท่ากับผลหารพีชคณิต

ตัวอย่างบางส่วน:

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

หรือ/สามารถใช้ตัวดำเนินการ:

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

อ้างอิง:


0

ฉันจะใช้ BigDecimal สำหรับการแก้ปัญหา แบบนี้:

    double value = 3.25;
    BigDecimal wholeValue = BigDecimal.valueOf(value).setScale(0, BigDecimal.ROUND_DOWN);
    double fractionalValue = value - wholeValue.doubleValue();

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

คำตอบนี้ถูกระบุว่ามีคุณภาพต่ำ หากตอบคำถามได้ให้ลองเพิ่มข้อความเพื่ออธิบายวิธีการทำงาน
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

0

ตกลงนี่อาจจะสายไป แต่ฉันคิดว่าแนวทางที่ดีที่สุดและแม่นยำกว่าคือการใช้ 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

หากคุณมีสองเท่าแสดงว่ามีความไม่แม่นยำในการลอยตัว การแปลงเป็น BigDecimal จะไม่คืนค่าความแม่นยำอย่างน่าอัศจรรย์

@Taschi ฉันคิดว่าคำถามเกี่ยวกับการแยก int และส่วนเศษส่วนไม่เกี่ยวกับการคืนค่าความแม่นยำ!
Omar Elashry

โอมาร์คุณพูดเป็นพิเศษเกี่ยวกับแนวทางของคุณว่า "ถูกต้องกว่า" ซึ่งฉันคิดว่าไม่เป็นความจริง คำตอบของคุณเป็นที่ยอมรับโดยสิ้นเชิง แต่ข้อความดังกล่าวดูเหมือนจะทำให้ฉันเข้าใจผิดซึ่งเป็นสาเหตุที่ฉันแสดงความคิดเห็น

@Taschi ฉันบอกว่าเพราะในหลาย ๆ คำตอบคุณจะสูญเสียคุณค่าเมื่อคุณได้ผลลัพธ์เช่นinput (5.03) output int = 5 , fractional = 0.0299999เรากำลังพูดถึงอินพุตและเอาต์พุตคุณใส่ค่าและรับค่าของคุณกลับมาโดยไม่สูญเสีย 0.001%! และแม่นยำไม่ทำให้เข้าใจผิด!
Omar Elashry

ใช่. คุณสูญเสียความแม่นยำเมื่อคุณจัดเก็บบางสิ่งเป็นสองเท่าในตอนแรก การปัดเศษเมื่อแปลงเป็น BigDecimal จะสูญเสียความแม่นยำเช่นกัน การสูญเสียความแม่นยำทั้งสองนี้อาจยกเลิกซึ่งกันและกัน แต่นั่นไม่ได้ "คืนค่า" ความแม่นยำเนื่องจากการคืนค่าความแม่นยำเป็นไปไม่ได้ในทางคณิตศาสตร์ คุณไม่สามารถดึงข้อมูลออกจากอากาศบาง ๆ

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

จะใช้ได้เฉพาะเมื่อตัวเลขมีทศนิยม 4 ตำแหน่งเท่านั้น ไม่ใช่อย่างอื่น
Marquis of Lorne
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.