¿Cómo obtengo partes enteras y fraccionarias del doble en JSP / Java?


104

¿Cómo obtengo partes enteras y fraccionarias del doble en JSP / Java? Si el valor es 3.25, entonces quiero obtener fractional =.25,whole = 3

¿Cómo podemos hacer esto en Java?


4
Parece tener una idea inexacta de lo que son la mantisa y el exponente. No son solo "parte completa" y "parte fraccionaria". Ver en.wikipedia.org/wiki/Floating_point
Jon Skeet

De hecho, leí alrededor de 5 publicaciones antes de decir 'hey ... eso no se llama exponente'. Mi cerebro tiró las palabras y comenzó a resolver el problema ... malos hábitos que me ha dado leer cosas de programación :)
Gishu

1
También reformule la pregunta OP .. para la posteridad, entre otras razones.
Gishu

1
Suena sospechosamente a un problema de tarea.
Brian Knoblauch

Oh, ya veo. Ya me preguntaba cómo obtiene resultados tan extraños
Johannes Schaub - litb

Respuestas:


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

Salidas:

Integer part = 2
Fractional part = 0.2999999999999998

61
En realidad, esta página es el primer resultado en una búsqueda de Google para "obtener parte fraccionada y completa de doble java" =)
Chris

12
En realidad, esta respuesta es incorrecta, ya que los valores más grandes que long pueden representar, dará números enormes en la parte fraccionaria. La respuesta de Dan Vinton a continuación es igual de simple y siempre devuelve el resultado correcto.
Arberg

2
así que, en realidad, esto no es correcto, como puede ver en el resultado. la entrada es una fracción de 3 y la salida es 29999999 ... usar BigDecimal en lugar de Double hará el truco sin embargo
Alex

2
@Alex No, la entrada es un número muy cercano 2.3, pero seguramente no 2.3. Y no hay nada de malo en la salida, a menos que desee mucho más de 10 dígitos válidos. Todo lo que necesita es algo de redondeo en cada salida (por ejemplo, formato %.9f) que generalmente es menos complicado que BigDecimal. El único problema aquí es el desbordamiento.
maaartinus

1
Convertir double en int es casi siempre una mala idea. Porque, por ejemplo, para (long)1.0e100obtendrá 0. Muchas veces necesita el valor doble simplemente "floored" para el que existe floor(). Si desea utilizar partes integrales y fraccionarias modf(). Realmente, esta es una mala respuesta.
mojuba

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

12
¿Por qué se vota negativamente? Funciona bien y con mi edición funcionará también con valores negativos.
HRJ

La parte entera podría ser => long longPart = (long) 3.25
jdurango

2
No funcionará para neg. valores. Es decir, -3,25% 1 = 0,75 no 0,25. Entonces, integralPart será -3.25 - 0.75 = -4.
WindRider

2
@WindRider, verifiqué negativo ... y funciona ... sin embargo, para lugares decimales que son pequeños en número, habrá un pequeño error. Ex. para -03.0025 devuelve -0.0024999999999999467 y -3.0
justshams

5
La confusión aquí es porque algunos lenguajes, como Python, usan %para significar módulo ( -3.25 % 1 == 0.75) y otros, como Java, Fortran, C y C ++, usan %para significar resto ( -3.25 % 1 == -0.25). WindRider puede haberlo escrito en un REPL de Python por conveniencia, pero esa respuesta es engañosa porque esta pregunta es sobre la JVM.
Jim Pivarski

24

Dado que esta pregunta de 1 año fue lanzada por alguien que corrigió el asunto de la pregunta, y esta pregunta está etiquetada jsp, y nadie aquí pudo dar una respuesta dirigida a JSP, aquí está mi contribución dirigida a JSP.

Utilice JSTL (simplemente coloque jstl-1.2.jar en /WEB-INF/lib) fmt taglib. Hay una <fmt:formatNumber>etiqueta que hace exactamente lo que quieres y de una manera bastante fácil con la ayuda de maxFractionDigitsy maxIntegerDigitsatributos.

Aquí hay un SSCCE , simplemente cópielo, péguelo y ejecútelo.

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

Salida:

Entero: 3

Fracción: .25

Eso es. No es necesario masajearlo con la ayuda de código Java sin procesar.


8

La pregunta original pedía el exponente y la mantisa, en lugar de la parte fraccionaria y entera.

Para obtener el exponente y la mantisa de un doble, puede convertirlo en la representación IEEE 754 y extraer los bits de esta manera:

long bits = Double.doubleToLongBits(3.25);

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

¿No está el primer bit de mantinssa establecido implícitamente en 1, por lo que la mantisa debería ser (bits & 0x000fffffffffffffL) | 0x0010000000000000L?
agnul

Rasmus no era una salida ryt Salida: exponente 0 y mantisa 2814749767106560 y si elige urs agnul, la mantisa es 0
Vinayak Bevinakatti

Roto con 4 votos a favor :) Aunque veo lo que el código está tratando de hacer al desarmar el valor doble en sus uniones, el código no parece generar los valores correctos.
Gishu

@agnul: Creo que "mantisa" generalmente se refiere solo al valor de los bits. Puede convertir esto al significado (a veces) anteponiendo un 1 bit. Pero según Wikipedia, la palabra mantisa ahora está en desuso en favor de "fracción".
Rasmus Faber

5

Lógica principal: primero tienes que encontrar cuántos dígitos hay después del punto decimal.
Este código funciona para cualquier número de hasta 16 dígitos. Si usa BigDecimal, puede ejecutarlo solo para hasta 18 dígitos. ponga el valor de entrada (su número) a la variable "num", aquí como ejemplo lo he codificado.

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

Amigo, esta es una respuesta extremadamente complicada para un problema simple. ¿Echaste un vistazo a la respuesta aceptada?
Gray

1
Ahora, la persona que votó en contra (no yo por cierto), debería haber explicado por qué hubo una votación en contra. Eso no es bueno. Pero todos obtuvimos una puntuación de 1 en algún momento.
Gray

2
@Gray, la pregunta era separar 3.25 como '3' y '25', y la respuesta aceptada nunca dará '25', siempre dará '2599999999'
OnePunchMan

@ Gray, sé quién lo rechazó, era un tipo llamado Eji (antiguo usuario) que se burlaba de todos y cada uno de mis comentarios, respuestas y preguntas que publico en este blog. Finalmente me quejo con el moderador.
OnePunchMan

2
Esta respuesta es muy útil si desea que la parte fraccionaria sea un entero
Guilherme Campos Hazan

5

La mantisa y el exponente de un número de coma flotante doble IEEE son los valores tales que

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

si la mantisa tiene la forma 0.101010101_base 2 (es decir, su bit más significativo se desplaza para estar después del punto binario) y el exponente se ajusta por sesgo.

Desde 1.6, java.lang.Math también proporciona un método directo para obtener el exponente insesgado (llamado getExponent (doble))

Sin embargo, los números que solicita son las partes integrales y fraccionarias del número, que se pueden obtener usando

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

aunque es posible que desee tratar los números negativos de manera diferente (floor(-3.5) == -4.0) , dependiendo de por qué desea las dos partes.

Sugiero encarecidamente que no los llame mantisa y exponente.


4

No sé si esto es más rápido pero estoy usando

float fp = ip % 1.0f;

3

[Editar: la pregunta originalmente preguntaba cómo obtener la mantisa y el exponente].

Donde n es el número para obtener la mantisa / exponente real:

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

O, para obtener la respuesta que estaba buscando:

exponent = int(n)
mantissa = n - exponent

Estos no son exactamente Java, pero deberían ser fáciles de convertir.


3

La parte entera se obtiene de la fundición simple y para la división de cadenas fraccionarias:

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

¿Qué pasa si su número es 2.39999999999999? Supongo que desea obtener el valor decimal exacto. Luego usa 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

Dado que la fmt:formatNumberetiqueta no siempre produce el resultado correcto, aquí hay otro enfoque solo de JSP: simplemente formatea el número como una cadena y hace el resto del cálculo en la cadena, ya que es más fácil y no implica más puntos flotantes 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>

Prueba todos los números de mi ejemplo. fmt:formatNumberRedondea su argumento, que no se desea en este caso.
Roland Illig

0

Muchas de estas respuestas tienen horribles errores de redondeo porque pasan números de un tipo a otro. Qué tal si:

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

@justshams ¿Qué pasa con el uso Math.abs?
Stephan

0

La respuesta aceptada no funciona bien para números negativos entre -0 y -1.0 También dé la parte fraccionaria negativa.

Por ejemplo: para el número -0,35

devoluciones

Parte entera = 0 Parte fraccionaria = -0,35

Si está trabajando con coordenadas GPS, es mejor obtener un resultado con el signo en la parte entera como:

Parte entera = -0 Parte fraccionaria = 0.35

Estos números se utilizan, por ejemplo, para las coordenadas GPS, donde es importante el signo de la posición Lat o Long

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

Salida:

Integer part = -0
Fractional part = 0,3500


0

Usaría BigDecimal para la solución. Me gusta esto:

    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 respuesta se ha marcado como de baja calidad. Si responde la pregunta, considere agregar un poco de texto para explicar cómo 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

De acuerdo, esto quizás sea tarde, pero creo que el mejor y más preciso enfoque es 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

Si tiene un doble, tiene imprecisión de flotación. Convertirlo en un BigDecimal no restaurará mágicamente su precisión.
Taschi

@Taschi creo que la pregunta es sobre separar el int y la parte fraccionaria, ¡no sobre restaurar su precisión!
Omar Elashry

Omar, hablaste específicamente de que tu enfoque es "más preciso", lo que creo que no es cierto. Su respuesta es totalmente aceptable, pero esa redacción me parece engañosa, por eso la comenté.
Taschi

@Taschi, dije que debido a que en muchas respuestas pierdes valor cuando obtienes la salida, por ejemplo input (5.03) output int = 5 , fractional = 0.0299999, estamos hablando de entradas y salidas, ¡pones valor y recuperas tu valor sin perder el 0.001%! ¡Y esto es exacto, no engañoso!
Omar Elashry

si. Pierde precisión cuando almacena algo como doble en primer lugar. El redondeo al convertir a BigDecimal también pierde precisión. Esas dos pérdidas de precisión pueden anularse entre sí, pero eso no "restaura" la precisión, porque restaurar la precisión es matemáticamente imposible. No puedes sacar información de la 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);
    }
}

Esto solo funciona si el número tiene exactamente 4 lugares decimales. De otro modo no.
Marqués de Lorne
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.