java - pasar - Conversión de BigDecimal a Entero
string to bigdecimal java 7 (8)
¿Has intentado llamar a BigInteger#intValue() ?
Tengo el método Hibernate que me devuelve un BigDecimal. Tengo otro método de API al que necesito pasar ese número pero acepta entero como parámetro. No puedo cambiar los tipos de devolución o los tipos de variable de ambos métodos.
Ahora, ¿cómo convertir el BigDecimal en Integer y pasarlo al segundo método?
¿Hay alguna forma de salir de esto?
¿Puede garantizar que BigDecimal
nunca contenga un valor mayor que Integer.MAX_VALUE
?
Si es así, entonces aquí está su código llamando intValue() :
Integer.valueOf(bdValue.intValue())
Bueno, podrías llamar a BigDecimal.intValue()
:
Convierte este BigDecimal en un int. Esta conversión es análoga a una conversión primitiva de estrechamiento de doble a corto como se define en la Especificación del lenguaje Java: cualquier parte fraccionaria de este BigDecimal será descartada, y si el "BigInteger" resultante es demasiado grande para caber en un int, solo el bajo -ordenador de 32 bits se devuelven. Tenga en cuenta que esta conversión puede perder información sobre la magnitud y precisión generales de este valor de BigDecimal, así como devolver un resultado con el signo opuesto.
A continuación, puede invocar explícitamente Integer.valueOf(int)
o dejar que auto-boxing lo haga por usted si está utilizando una versión suficientemente reciente de Java.
Descubrí que lo anterior no funcionó para mí. Estaba extrayendo un valor de celda de una JTable pero no pude convertir a doble o int, etc. Mi solución:
Object obj = getTable().getValueAt(row, 0);
donde la fila 0 siempre sería un número. Espero que esto ayude a cualquier persona que aún se desplaza!
Lo siguiente debería hacer el truco:
BigDecimal d = new BigDecimal(10);
int i = d.intValue();
myBigDecimal.intValueExact()
a myBigDecimal.intValueExact()
(o simplemente a intValue()
) e incluso lanzaría una excepción si perdería información. Eso devuelve un int pero el autoboxing se ocupa de eso.
TL; DR
Use uno de estos para necesidades de conversión universal
//Java 7 or below
bigDecimal.setScale(0, RoundingMode.DOWN).intValueExact()
//Java 8
bigDecimal.toBigInteger().intValueExact()
Razonamiento
La respuesta depende de cuáles sean los requisitos y cómo responda esta pregunta.
- ¿El
BigDecimal
potencialmente tendrá una parte fraccional distinta de cero? - ¿El
BigDecimal
potencialmente no cabe en el rango deInteger
? - ¿Le gustaría redondear o truncar partes fraccionales distintas de cero?
- ¿Cómo te gustaría redondear las partes fraccionales distintas de cero?
Si contestó no a las primeras 2 preguntas, podría simplemente usar BigDecimal.intValueExact()
como otros han sugerido y dejarlo explotar cuando ocurra algo inesperado.
Si no está 100% seguro con respecto a la pregunta número 2, entonces intValue()
siempre es la respuesta incorrecta.
Haciéndolo mejor
Usemos las siguientes suposiciones basadas en las otras respuestas.
- Estamos bien con perder precisión y truncar el valor porque eso es lo que
intValueExact()
y el auto-boxeo hacen - Queremos que se
BigDecimal
una excepción cuando elBigDecimal
sea más grande que el rangoInteger
porque cualquier otra cosa sería una locura a menos que tenga una necesidad muy específica de envoltura que ocurre cuando suelta los bits de orden superior.
Dados esos params, intValueExact()
arroja una excepción cuando no lo queremos si nuestra parte fraccionaria no es cero. Por otro lado, intValue()
no arroja una excepción cuando debería si nuestro BigDecimal
es demasiado grande.
Para obtener lo mejor de ambos mundos, BigDecimal
primero el BigDecimal
y luego BigDecimal
. Esto también tiene el beneficio de darle más control sobre el proceso de redondeo.
Prueba Spock Groovy
void ''test BigDecimal rounding''() {
given:
BigDecimal decimal = new BigDecimal(Integer.MAX_VALUE - 1.99)
BigDecimal hugeDecimal = new BigDecimal(Integer.MAX_VALUE + 1.99)
BigDecimal reallyHuge = new BigDecimal("10000000000000000000000000000000000000000000000")
String decimalAsBigIntString = decimal.toBigInteger().toString()
String hugeDecimalAsBigIntString = hugeDecimal.toBigInteger().toString()
String reallyHugeAsBigIntString = reallyHuge.toBigInteger().toString()
expect: ''decimals that can be truncated within Integer range to do so without exception''
//GOOD: Truncates without exception
'''' + decimal.intValue() == decimalAsBigIntString
//BAD: Throws ArithmeticException ''Non-zero decimal digits'' because we lose information
// decimal.intValueExact() == decimalAsBigIntString
//GOOD: Truncates without exception
'''' + decimal.setScale(0, RoundingMode.DOWN).intValueExact() == decimalAsBigIntString
and: ''truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception''
//BAD: hugeDecimal.intValue() is -2147483648 instead of 2147483648
//'''' + hugeDecimal.intValue() == hugeDecimalAsBigIntString
//BAD: Throws ArithmeticException ''Non-zero decimal digits'' because we lose information
//'''' + hugeDecimal.intValueExact() == hugeDecimalAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'''' + hugeDecimal.setScale(0, RoundingMode.DOWN).intValueExact() == hugeDecimalAsBigIntString
and: ''truncated decimal that cannot be truncated within Integer range throw conversionOverflow exception''
//BAD: hugeDecimal.intValue() is 0
//'''' + reallyHuge.intValue() == reallyHugeAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'''' + reallyHuge.intValueExact() == reallyHugeAsBigIntString
//GOOD: Throws conversionOverflow ArithmeticException because to large
//'''' + reallyHuge.setScale(0, RoundingMode.DOWN).intValueExact() == reallyHugeAsBigIntString
and: ''if using Java 8, BigInteger has intValueExact() just like BigDecimal''
//decimal.toBigInteger().intValueExact() == decimal.setScale(0, RoundingMode.DOWN).intValueExact()
}