Como obtenho partes inteiras e fracionárias de double em JSP / Java?


104

Como obtenho partes inteiras e fracionárias de double em JSP / Java? Se o valor for 3,25, então desejo obter fractional =.25,whole = 3

Como podemos fazer isso em Java?


4
Você parece ter uma ideia imprecisa do que são mantissa e expoente. Eles não são apenas "parte inteira" e "parte fracionária". Consulte en.wikipedia.org/wiki/Floating_point
Jon Skeet

Na verdade, eu li cerca de 5 posts antes de dizer 'hey .. isso não é chamado de expoente'. Meu cérebro jogou as palavras para fora e começou a resolver o problema ... os maus hábitos de ler coisas de programação me deram :)
Gishu

1
Além disso, reformule a questão OP .. para a posteridade, entre outras razões.
Gishu

1
Parece um problema de dever de casa.
Brian Knoblauch

ohh eu vejo. já me perguntei como ele consegue resultados tão estranhos
Johannes Schaub - litb

Respostas:


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

Saídas:

Integer part = 2
Fractional part = 0.2999999999999998

61
Na verdade, esta página é o primeiro resultado em uma pesquisa do Google por "get sliceal and Whole part out from double java" =)
Chris

12
Na verdade, esta resposta está incorreta, pois valores maiores do que longos podem representar isso resultará em números enormes na parte fracionária. A resposta de Dan Vinton abaixo é igualmente simples e sempre retorna o resultado correto.
arberg 01 de

2
então, na verdade, isso não está correto, como você pode ver na saída. a entrada é uma fração de 3 e a saída é 29999999 ... usar BigDecimal em vez de Double resolverá o problema
Alex

2
@Alex Não, a entrada é um número muito próximo 2.3, mas certamente não 2.3. E não há nada de errado com a saída, a menos que você queira muito mais do que 10 dígitos válidos. Tudo o que você precisa é de alguns arredondamentos em cada saída (por exemplo, formato %.9f), que geralmente é menos trabalhoso do que BigDecimal. O único problema aqui é o estouro.
maaartinus

1
Converter double em int é quase sempre uma má ideia. Porque, por exemplo, para (long)1.0e100você obterá 0. Muitas das vezes você precisa do valor duplo simplesmente "pavimentado" para o qual existe floor(). Se você quiser usar partes integrais e fracionárias modf(). Realmente, esta é uma resposta ruim.
mojuba

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

12
Por que isso foi rejeitado? Funciona bem, e minha edição funcionará com valores negativos também.
HRJ de

A parte inteira pode ser => longPart long = (long) 3.25
jdurango de

2
Não vai funcionar para neg. valores. Ie -3,25% 1 = 0,75 não 0,25. Portanto, integralPart será -3,25 - 0,75 = -4.
WindRider de

2
@WindRider, eu verifiquei o negativo .. e funciona .. entretanto para casas decimais que são pequenas em número, haverá um pequeno erro. Ex. para -03,0025 ele retorna -0,0024999999999999467 e -3,0
justshams

5
A confusão aqui é porque algumas linguagens, como Python, usam %para significar módulo ( -3.25 % 1 == 0.75) e outras, como Java, Fortran, C e C ++, usam %para significar resto ( -3.25 % 1 == -0.25). WindRider pode ter digitado em um REPL do Python para conveniência, mas essa resposta é enganosa porque esta pergunta é sobre a JVM.
Jim Pivarski

24

Uma vez que esta questão de 1 ano foi levantada por alguém que corrigiu o assunto da questão, e esta questão foi marcada com jsp, e ninguém aqui foi capaz de dar uma resposta direcionada ao JSP, aqui está minha contribuição direcionada ao JSP.

Use JSTL (apenas uma gota jstl-1.2.jar em /WEB-INF/lib) fmt taglib. Existe uma <fmt:formatNumber>tag que faz exatamente o que você deseja e de uma forma bastante fácil com ajuda de maxFractionDigitse maxIntegerDigitsatributos.

Aqui está um SSCCE , apenas copie e cole e execute -o.

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

Resultado:

Inteiro: 3

Fração: 0,25

É isso aí. Não há necessidade de massagear com a ajuda de código Java bruto.


8

A pergunta original pedia o expoente e a mantissa, ao invés da parte fracionária e inteira.

Para obter o expoente e a mantissa de um duplo, você pode convertê-lo na representação IEEE 754 e extrair os bits assim:

long bits = Double.doubleToLongBits(3.25);

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

O primeiro bit da mantinssa não é implicitamente definido como 1, então a mantissa deve ser (bits & 0x000fffffffffffffL) | 0x0010000000000000L?
agnul

Rasmus não era uma saída ryt Saída: expoente 0 e mantissa 2814749767106560 e se vc escolher urs agnul a mantissa é 0
Vinayak Bevinakatti

Quebrado com 4 votos positivos :) Embora eu veja o que o código está tentando fazer com a desmontagem do valor duplo em suas juntas, o código não parece gerar os valores corretos.
Gishu

@agnul: Acho que "mantissa" geralmente se refere apenas ao valor dos bits. Você pode apenas converter isso para o significando (às vezes) acrescentando 1 bit. Mas de acordo com a Wikipedia, a palavra mantissa agora é preterida em favor de "fração".
Rasmus Faber

5

Lógica principal, você deve primeiro descobrir quantos dígitos existem após o ponto decimal.
Este código funciona para qualquer número de até 16 dígitos. Se você usar BigDecimal, poderá executá-lo com até 18 dígitos. coloque o valor de entrada (seu número) na variável "num", aqui como um exemplo, codifiquei-o.

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

Cara, essa é uma resposta extremamente complicada para um problema simples. Você deu uma olhada na resposta aceita?
Gray,

1
Agora, a pessoa que fez o voto negativo (não eu, aliás) deveria ter explicado por que houve um voto negativo. Isso não é bom. Mas todos nós tínhamos uma pontuação de 1 em algum ponto ou outro.
Gray,

2
@Gray, a questão era separar 3.25 como '3' e '25', e a resposta aceita nunca fornecerá '25', sempre fornecerá '2599999999'
OnePunchMan

@Gray Eu sei quem deu downvote, foi um cara chamado Eji (usuário antigo) zombando de cada um dos meus comentários, respostas e perguntas que eu posto neste blog. Finalmente, reclamo com o moderador.
OnePunchMan de

2
Esta resposta é muito útil se você quiser a parte fracionária como um inteiro
Guilherme Campos Hazan

5

A mantissa e o expoente de um número de ponto flutuante duplo IEEE são os valores tais que

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

se a mantissa é da forma 0,101010101_base 2 (ou seja, seu bit mais significativo é deslocado para estar após o ponto binário) e o expoente é ajustado para polarização.

Desde 1.6, java.lang.Math também fornece um método direto para obter o expoente imparcial (chamado getExponent (double))

No entanto, os números que você está pedindo são as partes integrais e fracionárias do número, que podem ser obtidas usando

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

embora você possa tratar os números negativos de forma diferente (floor(-3.5) == -4.0), dependendo do motivo pelo qual deseja as duas partes.

Eu sugiro fortemente que você não os chame de mantissa e expoente.


4

Não sei se isso é mais rápido, mas estou usando

float fp = ip % 1.0f;

3

[Editar: a questão originalmente perguntada como obter a mantissa e o expoente.]

Onde n é o número para obter a mantissa / expoente real:

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

Ou, para obter a resposta que você estava procurando:

exponent = int(n)
mantissa = n - exponent

Eles não são exatamente Java, mas devem ser fáceis de converter.


3

A parte inteira obtém da conversão simples e para a divisão de string fracionária:

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

E se o seu número for 2.39999999999999. Suponho que você deseja obter o valor decimal exato. Em seguida, use 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

Visto que a fmt:formatNumbertag nem sempre produz o resultado correto, aqui está outra abordagem apenas JSP: ela apenas formata o número como string e faz o resto do cálculo na string, já que é mais fácil e não envolve mais ponto flutuante aritmética.

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

Experimente todos os números do meu exemplo. fmt:formatNumberarredonda seu argumento, o que não é desejado neste caso.
Roland Illig

0

Muitas dessas respostas têm erros de arredondamento horríveis porque estão lançando números de um tipo para outro. E se:

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

@justshams E quanto a usar Math.abs?
Stephan

0

A resposta aceita não funciona bem para números negativos entre -0 e -1,0. Forneça também a parte fracionária negativa.

Por exemplo: Para o número -0,35

retorna

Parte inteira = 0 Parte fracionária = -0,35

Se você estiver trabalhando com coordenadas GPS, é melhor ter um resultado com o sinal na parte inteira como:

Parte inteira = -0 Parte fracionária = 0,35

Esses números são usados, por exemplo, para coordenadas de GPS, onde são importantes o sinal para a posição Lat ou Longa

Propor código:

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

Resultado:

Integer part = -0
Fractional part = 0,3500


0

Eu usaria BigDecimal para a solução. Como isso:

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

Esta resposta foi marcada como de baixa qualidade. Se responder à pergunta, considere adicionar um pouco de texto para explicar como funciona.
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, talvez seja tarde, mas acho que a abordagem melhor e mais precisa é usar 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

Se você tiver um duplo, ele terá imprecisão de float. Convertê-lo em um BigDecimal não restaurará magicamente sua precisão.
Taschi

@Taschi acho que a questão é separar o int e a parte fracionária, e não restaurar sua precisão!
Omar Elashry

Omar, você falou especificamente sobre sua abordagem ser "mais precisa", o que eu acho que simplesmente não é verdade. Sua resposta é totalmente aceitável, mas essa formulação me parece enganosa, e é por isso que comentei sobre ela.
Taschi de

@Taschi, eu disse isso porque em muitas respostas você perde valor quando obtém a saída, por exemplo input (5.03) output int = 5 , fractional = 0.0299999, estamos falando de entradas e saídas, você coloca valor e recupera seu valor sem perder 0,001% dele! e isso é preciso, não enganoso!
Omar Elashry

sim. Você perde a precisão quando armazena algo como um duplo em primeiro lugar. O arredondamento ao converter para um BigDecimal também perde a precisão. Essas duas perdas de precisão podem se anular, mas isso não "restaura" a precisão, porque restaurar a precisão é matematicamente impossível. Você não pode extrair informações do nada.
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);
    }
}

Isso só funciona se o número tiver exatamente 4 casas decimais. De outra forma, não.
Marquês de Lorne
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.