Як отримати цілі та дробові частини з подвійних у JSP / Java?


104

Як отримати цілі та дробові частини з подвійних у JSP / Java? Якщо значення становить 3,25, я хочу отримати fractional =.25,whole = 3

Як ми можемо це зробити на Java?


4
У вас, здається, є неточне уявлення про те, що таке мантіса та показник. Вони не просто "ціла частина" і "дробова частина". Дивіться en.wikipedia.org/wiki/Floating_point
Джон Скіт

Насправді я прочитав близько 5 дописів, перш ніж піти "ей .. це не називається експонентом". Мій мозок викинув слова і почав вирішувати проблему .. шкідливі звички читати програмні речі дали мені :)
Gishu

1
Також будь ласка, переформулюйте питання OP .. для нащадків серед інших причин.
Gishu

1
Звучить підозріло, як проблема домашнього завдання.
Брайан Кноблауш

ой, бачу. Мені вже було цікаво, як він отримує настільки дивні результати
Йоганнес Шауб - ліб

Відповіді:


102

http://www.java2s.com/Code/Java/Data-Type/Obitingtheintegerandfractionalparts.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
Насправді ця сторінка є першим зверненням у пошуковій програмі google для "отримати дробову частину та цілу частину з подвійної Java" =)
Кріс

12
Насправді ця відповідь є невірною, оскільки значення, більші, ніж довгі, можуть представляти, вони дадуть величезну кількість у дробовій частині. Відповідь Дана Вінтона нижче так само проста і завжди повертає правильний результат.
Арберг

2
так що насправді це не правильно, як ви бачите у висновку. вхід є часткою 3, а вихід 29999999 ... за допомогою BigDecimal замість Double зробить трюк, хоча
Alex

2
@ Алекс Ні, вхід - це число, яке дуже близьке 2.3, але точно не 2.3. І з результатом немає нічого поганого, якщо ви не хочете набагато більше 10 дійсних цифр. Все, що вам потрібно, - це округлення кожного виводу (наприклад, формат %.9f), яке, як правило, менше болить, ніж BigDecimal. Єдина проблема тут - перелив.
maaartinus

1
Перетворення подвійного в int майже завжди погана ідея. Тому що, наприклад, (long)1.0e100ви отримаєте 0. Дуже багато разів вам потрібно подвійне значення просто "забитий", для якого є floor(). Якщо ви хочете використовувати як цілі, так і дробові частини modf(). Дійсно, це погана відповідь.
mojuba

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

12
Чому це заборонено? Добре працює, і з моєю редагуванням працюватимуть і з негативними значеннями.
HRJ

Ціла частина може бути => long longPart = (long) 3.25
jdurango

2
Не буде працювати за нег. значення. Тобто -3,25% 1 = 0,75 не 0,25. Тож інтегральна частина буде дорівнює -3,25 - 0,75 = -4.
WindRider

2
@WindRider, я перевірив на негативні .. та його роботи .. однак для десяткових знаків, малих за кількістю, буде незначна помилка. Вих. для -03.0025 повертається -0.0024999999999999467 та -3.0
justshams

5
Плутанина тут полягає в тому, що деякі мови, такі як Python, використовують %для позначення modulo ( -3.25 % 1 == 0.75) та інші, такі як Java, Fortran, C і C ++, %означають залишок ( -3.25 % 1 == -0.25). WindRider, можливо, ввів його у відповідь Python для відповіді, але ця відповідь вводить в оману, оскільки це питання стосується JVM.
Джим Піварський

24

Оскільки це питання для однорічного віку було порушено тим, хто виправляв тему питання, і це питання позначено тегами jsp, і ніхто тут не зміг дати цілеспрямовану відповідь на JSP, ось мій внесок, орієнтований на JSP.

Використовуйте JSTL (просто скиньте jstl-1.2.jar в /WEB-INF/lib) fmt таліб. Є <fmt:formatNumber>тег, який робить саме те, що ви хочете, і досить легко за допомогою maxFractionDigitsта maxIntegerDigitsатрибутів.

Ось SSCCE , просто скопіюйте його.

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

Чи не перший біт мантії неявно встановлений на 1, тому мантіса повинна бути (біти & 0x000fffffffffffffffL) | 0x0010000000000000L?
agnul

Rasmus це не було вихідного виходу Вихід: експонент 0 і mantissa 2814749767106560, а якщо ви обираєте ур agnul мантіса 0
Vinayak Bevinakatti

Розбитий на 4 голоси :) Хоча я бачу, що код намагається зробити, розбираючи подвійне значення на його стиках, але, схоже, код не видає потрібних значень.
Gishu

@agnul: Я думаю, що "mantissa" зазвичай посилається лише на значення бітів. Ви можете просто перетворити це в significand (іноді), попередньо додавши 1 біт. Але згідно з Вікіпедією, слово mantissa зараз застаріле на користь "дробу".
Расмус Фабер

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
Тепер особа, яка зробила перемогу (не мені), повинна була пояснити, чому відбулося голосування. Це не добре. Але у всіх нас в той чи інший момент була оцінка 1.
Сірий

2
@Gray запитання було розділити 3.25 як "3" і "25", і прийнята відповідь ніколи не дасть "25", вона завжди дасть "2599999999"
OnePunchMan

@Gray Я знаю, хто спричинив це, це було ім'я хлопця Eji (старий користувач), що глузує над кожним моїм коментарем, відповіддю та питаннями, які я публікую в цьому щоденнику. Нарешті я скаржуюся на модератора.
OnePunchMan

2
Ця відповідь дуже корисна, якщо ви хочете дробову частину як ціле число
Guilherme Campos Hazan

5

Значення мантіси та показника подвійного числа з плаваючою точкою IEEE є такими величинами, що

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

якщо мантіса має вигляд 0.101010101_база 2 (тобто її найбільш значущий біт зміщується на бінарну точку), а показник коригується на зміщення.

Починаючи з 1.6, java.lang.Math також забезпечує прямий метод отримання об'єктивного експонента (званий getExponent (подвійний))

Однак числа, про які ви запитуєте, є цілісною і дробовою частинами числа, яку можна отримати за допомогою

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?
Стефан

0

Прийнята відповідь не працює добре для від'ємних чисел від -0 до -1.0 Також дайте дробову частину негативною.

Наприклад: Для числа -0,35

повертає

Ціла частина = 0 Дробова частина = -0,35

Якщо ви працюєте з координатами GPS, то краще мати результат із знаком на цілій частині як:

Ціла частина = -0 Дробова частина = 0,35

Цифрові тези використовуються, наприклад, для координат GPS, де важливі знаки для ширини або довгої позиції

Код пропозиції:

    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 Я думаю, що питання полягає в розділенні внутрішньої і дробової частини, а не про відновлення її точності!
Омар Елашрі

Омар, ви спеціально говорили про те, що ваш підхід "точніший", що, на мою думку, просто не відповідає дійсності. Ваша відповідь цілком прийнятна, але таке формулювання здається мені оманливим, тому я прокоментував це.
Тащі

@Taschi, я сказав, що через те, що у багатьох відповідях ви втрачаєте значення, коли отримуєте вихід, наприклад input (5.03) output int = 5 , fractional = 0.0299999, ми говоримо про входи та виходи, u додайте значення і поверніть свою вартість, не втрачаючи 0,001%! і це точно, не вводити в оману!
Омар Елашрі

так. Ви втрачаєте точність, коли зберігаєте що-небудь як подвійне. Округлення при переході до 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 знаки після коми. Не інакше.
Маркіз Лорн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.