Clase decimal liviana de Java

votos
12

Estoy considerando escribir dos alternativas de precisión limitadas a BigDecimal, a saber, DecimalInt y DecimalLong. Estos serían capaces de tratar con números dentro de los límites reales de int y long con un número arbitrario de decimales, creables en forma mutable e inmutable. Mi plan es hacer que DecimalInt soporte +/- 999,999,999 a +/- 0,999999999 y DecimalLong igual, pero con hasta 18 dígitos.

Esto se haría manteniendo un valor de conteo de dígitos decimales de 0-9 para DecimalInt y de 0-18 para DecimalLong junto con el valor real almacenado como una escala int o larga. El uso normal sería para números pequeños de decimales, como por ejemplo dinero y precios de acciones, generalmente 2-4 lugares decimales.

Los requisitos esenciales son (a) espacio reducido (2 clases, más OverflowException), y (b) soporte total de todas las operaciones básicas más todas las matemáticas que tengan sentido.

Buscar resultados en Google no arrojó ningún resultado obvio: todos parecían pertenecer a decimales arbitrarios.

Mis preguntas son: ¿Ya se ha hecho esto? ¿Hay sutilezas ocultas en esto y por eso todavía no se ha hecho? ¿Alguien ha escuchado rumores de que Java sea compatible con un tipo decimal como el de DotNet?

EDITAR: Esto es diferente de BigDecimal porque debe ser (a) mucho más eficiente no tratar con una matriz de entradas, y (b) no ajustará BigInteger, por lo que será más eficiente en la memoria, y (c) tendrá una opción mutable por lo que será más rápido allí también. En resumen, menos sobrecarga para casos de uso simple como Quiero almacenar un saldo bancario sin la sobrecarga de BigDecimal y la inexactitud del doble.

EDITAR: Tengo la intención de hacer todos los cálculos utilizando int o largo para evitar el problema clásico de: 1586.60-708.75 = 877.8499999999999 en lugar de 877.85

Publicado el 09/12/2008 a las 21:05
fuente por usuario
En otros idiomas...                            


5 respuestas

votos
12

Sospecho fuertemente que la razón por la que esto no se ha hecho es que la sobrecarga de BigDecimal y BigInteger no es tan relevante como piensas, y evitarlo no vale la pena el esfuerzo y el riesgo de equivocarte de una manera sutil.

Para usar su ejemplo: para cualquier aplicación financiera, guardar unas pocas docenas de bytes es una cuestión de poca importancia y de precisión limitada, un factor decisivo (los precios de las acciones suelen ser de 2 a 4 dígitos en EE. UU., Pero si desea tratar con mercados emergentes) , encontrará monedas con inflación galopante, donde una suma de 15 dígitos le compra la mitad de una barra de pan).

Básicamente, suena como otro caso de optimización prematura.

Respondida el 11/12/2008 a las 11:39
fuente por usuario

votos
1

La mayoría de las personas que están particularmente preocupados por los errores de redondeo utilizan BigDecimal y BigInteger que realiza bastante bien en la mayoría de las situaciones.

Sin embargo, los casos en que el rendimiento es más crítica, utilizando doble con redondeo hace el trabajo. Esto es a menudo olvidado por los novatos, pero no se puede simplemente dar un resultado doble sin redonda sensible y esperar obtener una respuesta sensata.

En la gran mayoría de los casos se duplica con redondeo es todo lo que necesita.

System.out.printf("%.2f%n", 1586.60-708.75);

huellas dactilares

877.85
Respondida el 24/11/2010 a las 00:03
fuente por usuario

votos
0

Si está mirando un número fijo y pequeño de decimales para manejar dinero, entonces esto generalmente se hace manteniendo números enteros (largos si es necesario) de centavos o centésimas de centavo.

Si está tratando con dinero, deberá tener cuidado con la forma en que maneja el redondeo. Si sus cálculos van a ser auditados, hay reglas sobre cómo se hace ese tipo de cosas. También supongo que sabe que algunas operaciones no se pueden llevar a cabo con precisión (la división es el ejemplo obvio).

Respondida el 10/12/2008 a las 15:38
fuente por usuario

votos
0

Si su enfoque es para dispositivos portátiles, mire Real . Real permite que la precisión del número se establezca de 0 a 16. Está diseñado para teléfonos celulares MIDP.

También de interés, mira la biblioteca de reals constructivos . Aunque no es liviano.

En referencia al siguiente comentario, ¿no puedes usar la Biblioteca de Matemáticas de Apache Commons para trabajar con fracciones? ¿Hay alguna razón que no funcionará?

Respondida el 09/12/2008 a las 21:31
fuente por usuario

votos
-1

Me parece que si quiere precisión arbitraria necesitará un número indefinido de bits para representar la mantisa. Eso significa que algún tipo de estrategia de asignación de matriz va a ser necesaria para la mantisa. Puede crear el suyo aquí, pero BigInteger lo hace de manera bastante eficiente y funciona

Debe especificar cuál es el valor más pequeño (distinto de cero) que necesita representar. Esto será 10 ^ - (2 ^ n), donde n + 1 es el número de bits que asigna al exponente. Con BigDecimal esto es 10 ^ - (2 ^ 31). Podría usar un exponente de tamaño arbitrario, pero ese rango debería ser suficiente para cualquiera.

Entonces, lo que necesitas es una mantisa entera sin límites para darte la precisión arbitraria y un exponente de tamaño fijo, dependiendo de lo que quieras que sea tu valor mínimo representable. Esencialmente esto es BigDecimal; el único cambio es que usará algún objeto más pequeño en lugar del int utilizado por BigDecimal. Dudo que el ahorro de espacio valga la pena. Creo que BigDecimal hará lo que necesita con apenas más uso de memoria que cualquier solución que usted mismo cree.

Por supuesto, puede elegir una cantidad máxima de cifras significativas que necesitará; entonces necesitas almacenamiento de tamaño fijo para mantisa y exponente, y eso es mucho menos almacenamiento. Solo usa un número fijo de largos como la mantisa.

Respondida el 09/12/2008 a las 23:43
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more