Làm cách nào để lấy toàn bộ và các phần phân đoạn từ gấp đôi trong JSP / Java?


104

Làm cách nào để lấy toàn bộ và các phần phân đoạn từ gấp đôi trong JSP / Java? Nếu giá trị là 3,25 thì tôi muốn lấy fractional =.25,whole = 3

Làm thế nào chúng ta có thể làm điều này trong Java?


4
Bạn dường như có một ý tưởng không chính xác về định trị và số mũ là gì. Chúng không chỉ là "toàn bộ phần" và "phần phân đoạn". Xem en.wikipedia.org/wiki/Floating_point
Jon Skeet

Trên thực tế, tôi đã đọc khoảng 5 bài viết trước khi đi 'này .. đó không được gọi là số mũ'. Bộ não của tôi đã ném ra những lời và bắt đầu giải quyết vấn đề .. thói quen xấu đọc lập trình thứ đã cho tôi :)
Gishu

1
Cũng xin vui lòng nói lại câu hỏi OP .. cho hậu thế trong số các lý do khác.
Gishu

1
Nghe có vẻ đáng ngờ như một bài toán về nhà.
Brian Knoblauch

Ồ, tôi hiểu rồi. tôi đã tự hỏi làm thế nào ông nhận được kết quả rất lạ
Johannes Schaub - litb

Câu trả lời:


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

Kết quả đầu ra:

Integer part = 2
Fractional part = 0.2999999999999998

61
Trên thực tế, trang này là lần truy cập đầu tiên trên một tìm kiếm trên google cho "get fractional and whole part out from double java" =)
Chris

12
Trên thực tế câu trả lời này không chính xác, đối với các giá trị lớn hơn long có thể đại diện, nó sẽ cung cấp các con số rất lớn trong phần phân số. Câu trả lời của Dan Vinton dưới đây rất đơn giản và luôn trả về kết quả chính xác.
arberg

2
vì vậy trên thực tế, điều này không chính xác, như bạn có thể thấy trong đầu ra. đầu vào là phần của 3 và đầu ra là 29999999 ... sử dụng BigDecimal thay vì Double sẽ thực hiện thủ thuật
Alex

2
@Alex Không, đầu vào là một số rất gần với 2.3, nhưng chắc chắn là không 2.3. Và không có gì sai với đầu ra, trừ khi bạn muốn nhiều hơn 10 chữ số hợp lệ. Tất cả những gì bạn cần là làm tròn số trong mỗi đầu ra (ví dụ: định dạng %.9f) thường ít gây đau hơn BigDecimal. Vấn đề duy nhất ở đây là tràn.
maaartinus

1
Chuyển đổi double sang int hầu như luôn là một ý tưởng tồi. Bởi vì ví dụ đối với (long)1.0e100bạn sẽ nhận được 0. Rất nhiều lần bạn cần giá trị gấp đôi chỉ đơn giản là "floored" mà có floor(). Nếu bạn muốn sử dụng cả hai phần tích phân và phân số modf(). Thực sự, đây là một câu trả lời tồi.
mojuba

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

12
Tại sao điều này bị phản đối? Hoạt động tốt và với bản chỉnh sửa của tôi cũng sẽ hoạt động với các giá trị âm.
HRJ

Phần số nguyên có thể là => long longPart = (dài) 3,25
jdurango

2
Sẽ không hiệu quả đối với người tiêu cực. các giá trị. Tức là -3,25% 1 = 0,75 chứ không phải 0,25. Vì vậy, phần tích phân sẽ là -3,25 - 0,75 = -4.
WindRider

2
@WindRider, tôi đã kiểm tra số âm .. và các hoạt động của nó .. tuy nhiên đối với các chữ số thập phân có số lượng nhỏ, sẽ có một lỗi nhỏ. Ví dụ. cho -03,0025 nó trả về -0,0024999999999999467 và -3,0
justshams

5
Sự nhầm lẫn ở đây là vì một số ngôn ngữ, chẳng hạn như Python, sử dụng %nghĩa là modulo ( -3.25 % 1 == 0.75) và những ngôn ngữ khác, chẳng hạn như Java, Fortran, C và C ++, sử dụng %nghĩa là phần dư ( -3.25 % 1 == -0.25). WindRider có thể đã nhập nó vào Python REPL để có tính hiệu quả, nhưng câu trả lời đó gây hiểu lầm vì câu hỏi này là về JVM.
Jim Pivarski,

24

Vì câu hỏi 1 năm tuổi này được khởi động bởi một người đã sửa chủ đề câu hỏi, và câu hỏi này đã được gắn thẻ jspvà không ai ở đây có thể đưa ra câu trả lời nhắm mục tiêu JSP, đây là đóng góp nhắm mục tiêu JSP của tôi.

Sử dụng JSTL (chỉ cần thả jstl-1.2.jar vào /WEB-INF/lib) fmt taglib. Có một <fmt:formatNumber>thẻ thực hiện chính xác những gì bạn muốn và theo cách khá dễ dàng với sự trợ giúp của maxFractionDigitsmaxIntegerDigitsthuộc tính.

Đây là một SSCCE , chỉ cần copy'n'paste'n'run nó.

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

Đầu ra:

Toàn bộ: 3

Phân số: 0,25

Đó là nó. Không cần phải xoa bóp nó với sự trợ giúp của mã Java thô.


8

Câu hỏi ban đầu yêu cầu phần lũy thừa và phần định trị, thay vì phần phân số và phần nguyên.

Để lấy số mũ và phần định trị từ một nhân đôi, bạn có thể chuyển đổi nó thành biểu diễn IEEE 754 và trích xuất các bit như sau:

long bits = Double.doubleToLongBits(3.25);

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

Không phải bit đầu tiên của phần định trị được đặt ngầm định là 1, vì vậy phần định trị phải là (bit & 0x000fffffffffffffL) | 0x0010000000000000L?
agnul

Rasmus nó wasnt một Output ra ryt: số mũ 0 và mantissa 2814749767106560 và nếu u chọn urs agnul mantissa là 0
Vinayak Bevinakatti

Bị hỏng với 4 phiếu bầu trở lên :) Mặc dù tôi thấy mã đang cố gắng làm gì với việc tách đôi giá trị ở các khớp của nó, mã dường như không xuất ra các giá trị phù hợp.
Gishu

@agnul: Tôi nghĩ "phần định trị" thường chỉ đề cập đến giá trị của các bit. Bạn có thể chỉ cần chuyển đổi điều này thành ý nghĩa và (đôi khi) viết trước một chút. Nhưng theo Wikipedia, từ mantissa hiện đã không còn được dùng để chuyển sang "phân số".
Rasmus Faber

5

Logic chính trước tiên bạn phải tìm xem có bao nhiêu chữ số sau dấu thập phân.
Mã này hoạt động cho bất kỳ số nào có tối đa 16 chữ số. Nếu bạn sử dụng BigDecimal, bạn có thể chạy nó chỉ với tối đa 18 chữ số. đặt giá trị đầu vào (số của bạn) vào biến "num", đây là một ví dụ tôi đã mã hóa nó.

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

Anh bạn, đây là một câu trả lời cực kỳ phức tạp cho một vấn đề đơn giản. Bạn đã xem qua câu trả lời được chấp nhận chưa?
Màu xám,

1
Bây giờ người đã bỏ phiếu xuống (không phải tôi btw), lẽ ra phải giải thích tại sao lại có một cuộc bỏ phiếu xuống. Điều đó không tốt. Nhưng tất cả chúng tôi đều bị điểm 1 ở điểm này hay cách khác.
Màu xám,

2
@Gray câu hỏi là tách 3,25 thành "3" và "25", và câu trả lời được chấp nhận sẽ không bao giờ cho "25", nó sẽ luôn cho "2599999999"
OnePunchMan 15/10/13

@Gray Tôi biết ai đã phản đối nó, đó là một anh chàng tên Eji (người dùng cũ) chế nhạo từng nhận xét, câu trả lời và câu hỏi của tôi mà tôi đăng trên blog này. Cuối cùng tôi phàn nàn với người điều hành.
OnePunchMan

2
Anwer này rất hữu ích nếu bạn muốn các phần phân đoạn là một số nguyên
Guilherme Campos Hazan

5

Phần định trị và số mũ của một số dấu chấm động kép IEEE là các giá trị sao cho

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

nếu phần định trị có dạng 0.101010101_base 2 (nghĩa là bit quan trọng nhất của nó được chuyển sang sau điểm nhị phân) và số mũ được điều chỉnh theo độ chệch.

Kể từ 1.6, java.lang.Math cũng cung cấp một phương thức trực tiếp để lấy số mũ không chệch (được gọi là getExponent (double))

Tuy nhiên, những con số bạn đang yêu cầu là phần tích phân và phần thập phân của số, có thể lấy được bằng cách sử dụng

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

mặc dù bạn có thể muốn đối xử với số âm theo cách khác (floor(-3.5) == -4.0) , tùy thuộc vào lý do tại sao bạn muốn hai phần.

Tôi thực sự khuyên bạn không nên gọi những phần định trị và số mũ này.


4

Không biết cái này có nhanh hơn không nhưng tôi đang dùng

float fp = ip % 1.0f;

3

[Chỉnh sửa: Câu hỏi ban đầu hỏi cách lấy phần định trị và số mũ.]

Trong đó n là số nhận phần định trị / số mũ thực:

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

Hoặc, để nhận được câu trả lời bạn đang tìm kiếm:

exponent = int(n)
mantissa = n - exponent

Đây không phải là Java chính xác nhưng nên dễ dàng chuyển đổi.


3

Phần số nguyên nhận được từ quá trình ép đơn giản và để tách phân số - chuỗi:

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

Nếu số của bạn là 2.39999999999999 thì sao. Tôi cho rằng bạn muốn lấy giá trị thập phân chính xác. Sau đó, sử dụng 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:formatNumberthẻ không phải lúc nào cũng mang lại kết quả chính xác, đây là một cách tiếp cận khác chỉ dành cho JSP: Nó chỉ định dạng số dưới dạng chuỗi và thực hiện phần còn lại của tính toán trên chuỗi, vì điều đó dễ dàng hơn và không liên quan đến dấu phẩy động nữa số học.

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

Chỉ cần thử tất cả các con số từ ví dụ của tôi. fmt:formatNumberlàm tròn đối số của nó, điều này không được mong muốn trong trường hợp này.
Roland Illig

0

Rất nhiều câu trả lời trong số này có lỗi làm tròn kinh khủng vì chúng đang chuyển số từ loại này sang loại khác. Làm thế nào về:

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

@justshams Còn việc sử dụng Math.absthì sao?
Stephan

0

Câu trả lời được chấp nhận không hoạt động tốt đối với các số âm trong khoảng từ -0 đến -1.0 Đồng thời cung cấp cho phần phân số âm.

Ví dụ: Cho số -0,35

trả lại

Phần nguyên = 0 Phần thập phân = -0,35

Nếu bạn đang làm việc với tọa độ GPS, tốt hơn nên có kết quả với dấu hiệu trên phần nguyên là:

Phần nguyên = -0 Phần thập phân = 0,35

Các số của luận án được sử dụng chẳng hạn cho tọa độ GPS, đâu là dấu hiệu quan trọng cho vị trí Vĩ độ hoặc Kinh độ

Đề xuất mã:

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

Đầu ra:

Integer part = -0
Fractional part = 0,3500

0

Kể từ Java 8, bạn có thể sử dụng Math.floorDiv.

Nó trả về giá trị lớn nhất (gần nhất với dương vô cùng) int nhỏ hơn hoặc bằng thương đại số.

Vài ví dụ:

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

Ngoài ra, /có thể sử dụng toán tử:

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

Người giới thiệu:


0

Tôi sẽ sử dụng BigDecimal cho giải pháp. Như thế này:

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

Câu trả lời này đã được gắn cờ là chất lượng thấp. Nếu nó trả lời câu hỏi, hãy cân nhắc thêm một chút văn bản để giải thích cách nó hoạt động.
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

OK, điều này có thể muộn, nhưng tôi nghĩ cách tiếp cận tốt nhất và chính xác hơn là sử dụng 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

Nếu bạn có một đôi, nó có tính không chính xác float. Chuyển đổi nó thành BigDecimal sẽ không khôi phục độ chính xác một cách kỳ diệu.
Taschi

@Taschi Tôi nghĩ câu hỏi là về việc tách phần int và phần phân số, không phải về việc khôi phục độ chính xác của nó!
Omar Elashry

Omar, bạn đã nói cụ thể về cách tiếp cận của bạn là "chính xác hơn", điều mà tôi nghĩ là không đúng. Câu trả lời của bạn là hoàn toàn có thể chấp nhận được nhưng từ ngữ đó dường như gây hiểu lầm cho tôi, đó là lý do tại sao tôi nhận xét về nó.
Taschi

@Taschi, tôi đã nói rằng bởi vì trong nhiều câu trả lời, bạn sẽ mất giá trị khi nhận được đầu ra, ví dụ: input (5.03) output int = 5 , fractional = 0.0299999chúng ta đang nói về đầu vào và đầu ra, bạn hãy đặt giá trị và nhận lại giá trị của bạn mà không mất 0,001%! và điều này chính xác, không gây hiểu lầm!
Omar Elashry

Đúng. Bạn mất độ chính xác khi bạn lưu trữ một thứ gì đó ở vị trí gấp đôi ngay từ đầu. Việc làm tròn khi chuyển đổi thành BigDecimal cũng làm mất độ chính xác. Hai điểm mất độ chính xác đó có thể triệt tiêu lẫn nhau, nhưng điều đó không "khôi phục" độ chính xác, bởi vì việc khôi phục độ chính xác về mặt toán học là không thể. Bạn không thể lấy thông tin ra khỏi không khí mỏng.
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);
    }
}

Điều này chỉ hoạt động nếu số có chính xác 4 chữ số thập phân. Không khác.
Marquis of Lorne,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.