170

Unas veces los cálculos funcionan correctamente, pero otras veces no:

> 0.1 + 0.1
0.2 // correcto
> 0.1 + 0.2
0.30000000000000004 // ¿qué?
> 10 * 0.67
6.7 // correcto
> 10 * 0.68
6.800000000000001 // demasiado grande
> 10 * 0.69
6.8999999999999995 // demasiado pequeño

(Estos ejemplos están escritos en JavaScript, pero el mismo problema existe en muchos lenguajes de programación)

Estos cálculos son bastante fáciles: creo que todos podemos hacerlos en un momento. ¿Por qué mis programas no pueden hacer cálculos aritméticos correctamente, y qué puedo hacer si necesito resultados más precisos?

Carlos Muñoz
  • 12,864
  • 2
  • 42
  • 62
Peter Olson
  • 4,645
  • 3
  • 18
  • 22
  • 10
    @manix En el SO inglés hay la etiqueta [`language-agnostic`](http://stackoverflow.com/questions/tagged/language-agnostic). Es una de mis etiquetas favoritas por que estas preguntas generalmente son mas interesantes para mi que las problemas con tecnologías especificas. Pero si le parece de todas maneras que no tiene sentido, podemos discutir esto en Meta. – Peter Olson Dec 02 '15 at 06:54
  • Si usted simplemente no quiere ver a todos esos decimales adicionales: tiene "puede" formatear el resultado, redondeado a un número fijo de decimales que desea usar, quizas esto le ayude, http://www.w3schools.com/js/js_math.asp lo siento pero no uso javascript, puede usar por ejemplo Math.round() Math.ceil() Math.floor(), o algún tipo de cast teneniendo en cuenta la perdida de información pero no se si eso es posible en JS. – Angel Angel Dec 02 '15 at 06:57
  • 4
    Información en http://puntoflotante.org/ – astrojuanlu Dec 02 '15 at 08:58
  • 3
    No veo necesario crear una respuesta para esto pero un recurso bastante extensivo y abarcativo sobre el tema de coma flotante: [What Every Computer Scientist Should Know About Floating-Point Arithmetic](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – drielnox Dec 02 '15 at 13:42
  • 2
    Hay que mejorar mucho en la traducción de las etiquetas. "lenguaje-no-importa" no es ni constructivo ni diciente. – dwarandae Dec 02 '15 at 17:10
  • @dwarandae Perdóname, no soy un hablante nativo. Si usted tiene traducciones mejores, por favor edite las etiquetas. – Peter Olson Dec 03 '15 at 00:57
  • @JoseAntonioDuraOlmos independiente-del-lenguaje tiene 26 caracteres, la longitud máxima es de 25 caracteres. – Peter Olson Dec 04 '15 at 00:33
  • @drielnox Hay una mejor artículo para programadores: [What Every Programmer Should Know About Floating-Point Arithmetic, or, Why don’t my numbers add up?](http://floating-point-gui.de/). Y tiene una versión española: **[Lo que todo programador debería saber sobre aritmética de punto flotante, o, ¿Por qué mis números no se suman bien?](http://puntoflotante.org/)** Es útil tenerlo aquí, porque habrá muchos duplicados de esta pregunta. – Gilles 'SO- stop being evil' Dec 04 '15 at 12:40
  • 3
    Hola, @PeterOlson si esta o cualquier otra respuesta ha resuelto su problema, por favor considera [aceptarla](http://meta.stackexchange.com/q/5234/179419) clicando la marca de check (en forma de V debajo de la puntuación de la respuesta). Esto indica a la comunidad que has encontrado una solución y de paso os dará reputación a ambos (a tí y quien ha respondido). Por supuesto, no hay ninguna obligación de hacer esto. – Jordi Castilla Jan 28 '16 at 15:07

12 Answers12

187

El problema viene de la limitación que los ordenadores tienen para representar números de coma flotante usando un número finito de bits.

En este artículo en inglés hay una muy buena explicación. Básicamente, para representar el número 0.1 en coma flotante necesitamos un número infinito de dígitos binarios:

Dividiendo 1 entre 10 en binario

Dividiendo 1 entre 10 en binario

1/10 en binario (primeros 1369 dígitos)

1/10 en binario (primeros 1369 dígitos)

Si suponemos que nuestro ordenador es capaz de almacenar hasta 53 dígitos, una vez truncado nuestro 0.1 queda representado en binario como:

0.0001100110011001100110011001100110011001100110011001101

...que en decimal es

0.1000000000000000055511151231257827021181583404541015625

Para este problema hay básicamente dos soluciones:

  • Usar un tipo decimal exacto en vez de coma flotante. Hay lenguajes que proporcionan estos tipos nativamente (por ejemplo, .NET tiene el tipo decimal); para los que no, suele haber librerías especializadas para ello (por ejemplo decimal.js para Javascript).
  • Si el número de decimales se conoce por adelantado (por ejemplo al tratar con valores monetarios), los valores se pueden representar como enteros. Así, 123.45€ se representaría como 12345 céntimos. El punto decimal se añadiría al final, a la hora de mostrar el valor al usuario.

Un buen sitio con más información sobre este tema: http://puntoflotante.org

Konamiman
  • 5,068
  • 2
  • 21
  • 44
  • Otro ejemplo que puede ayudar en caso de que quede alguna duda: 1/3 no es representable de forma exacta en base decimal (0.333333...), pero sí lo es en base 3 (0.1). De forma análoga, en base 2 también hay números periódicos que no se pueden representar de forma exacta, u otros no periódicos cuyo valor exacto supera la precisión de la variable utilizada (la precisión _infinita_ no es existe en computación ya que la propia memoria no es infinita). – cbuchart Jul 04 '17 at 08:09
  • Esta es una respuesta que merecería un `+2` en lugar de `+1`. Muy Interesante. Cada día se aprende algo nuevo. – David E. Luna M. Feb 21 '21 at 04:59
  • El comentario de arriba tiene un pequeño error. 0.33333333 no se escribe 0.1 en binario porque realmente 0.1 equivale 0.5. – JosephGen Apr 15 '21 at 02:27
62

Muchos lenguajes de programación, según el estándar IEE754, representan números en una representación de coma flotante en la base binaria.

Este sistema es similar a la notación científica. En ese sistema se pueden representar números así:

  • 1,23 x 10-5 para 0,0000123
  • 1,23 x 101 para 12,30
  • 1,23 x 108 para 123.000.000

En este sistema (realmente, en cualquier sistema finito), hay números que no se pueden representar con exactitud. Por ejemplo, 1/3 o 543/37 o pi. Sólo podemos representar aproximaciones. Con diez dígitos significativos:

  • 0,3333333333 x 100 para 1/3
  • 1,467567568 x 10-1 para 543/37
  • 3,141592654 x 100 para pi

De la misma manera, las programas que usan el sistema binario pueden representar algunos números exactamente:

  • 1,1101 x 28 para 1110100002 (46410)
  • 1,1101 x 21 para 11,1012 (3,62510)
  • 1,1101 x 2-5 para 0,0000111012 (0,05664062510)

pero algunos números no. Con 16 bits significativos, podemos representar aproximaciones de números así:

  • 1,1001100110011001 x 2-4 (igual a 0,0999994277954101562510) para 1/10
  • 1,0101010101010101 x 2-2 (igual a 0,33333206176757812510) para 1/3
  • 1,1001001000011111 x 21 (igual a 3,14157104492187510) para pi

A veces parece que los cálculos son exactos cuando en realidad no lo son, por ejemplo:

> 0.1 + 0.1
0.2

0,1 y 0,2 no tienen representación exacta en binario, pero en este programa parece que no hay problemas. Esto es una consecuencia del algoritmo para la presentación de los números. Bajo el capó se calcula así:

> 0.100000000000000005551115123126 + 0.100000000000000005551115123126
0.200000000000000011102230246252

pero se presentan como 0.1 y 0.2 porque son más o menos "bastante cercanos".


¿Qué puedo hacer si necesito resultados más precisos?

Hay diferentes soluciones con diferentes tecnologías:

  • Algunos lenguajes y bibliotecas proporcionan un tipo decimal, por ejemplo lenguajes de .NET, Python, y Ruby. Todavía no se pueden representar todos los números racionales (por ejemplo 1/3) exactamente, pero este tipo es útil para representar cantidades de dinero. Para dinero también se puede usar números enteros.
  • Hay bibliotecas en diferentes lenguajes si necesitas precisión arbitraria (por ejemplo BigDecimal en Java o BigRational.js en JavaScript).
A. Cedano
  • 86,578
  • 19
  • 122
  • 221
Peter Olson
  • 4,645
  • 3
  • 18
  • 22
  • 1
    Aunque 1/3 no se puede representar con un tipo decimal, sí es posible representarlo exáctamente con otros tipos. Basta crear una clase de racionales que contenga 2 valores : numerador y denominador. De hecho, es posible representar en un programa de ordenador todos los números que pueden ser representados en castellano, sin excepciones. – Anonymous Coward Dec 03 '15 at 11:54
  • Encontré este enlace sobre el IEEE 754, no convierte el número pero hay botones para ir aproximándose al número. https://www.h-schmidt.net/FloatConverter/IEEE754.html La cosa es que intenté probar 1/10 y en vez de salir `0,09999942779541015625` sale `0.100000001490116119384765625`, muestro una captura de pantalla. https://i.stack.imgur.com/u19hl.png y si le quito el último check sale `0.0999999940395355224609375 `. Para este número `0.09999942779541015625` en realidad. Recién me doy cuenta que eran 16 bits. –  Feb 15 '20 at 02:16
51

Tus programas sí pueden hacer cálculos aritméticos correctamente.

Por ejemplo, con el programa bc :

jose@luthien ~ $ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
0.1+0.1
.2
0.1+0.2
.3
10*0.67
6.70
10*0.68
6.80
10*0.69
6.90

Con Java :

package testmatematicas;
import java.math.BigDecimal;
public class TestMatematicas {
    public static void main(String[] args) {
        BigDecimal ceroPuntoUno = new BigDecimal("0.1");
        BigDecimal suma = ceroPuntoUno.add( ceroPuntoUno );
        System.out.println( suma );
        BigDecimal ceroPuntoDos = new BigDecimal("0.2");
        suma = ceroPuntoUno.add(ceroPuntoDos);
        System.out.println( suma );
        BigDecimal diez = new BigDecimal("10");
        BigDecimal ceroPuntoSesentaYSiete = new BigDecimal("0.67");
        BigDecimal multiplicacion = diez.multiply(ceroPuntoSesentaYSiete);
        System.out.println( multiplicacion );
        BigDecimal ceroPuntoSesentaYOcho = new BigDecimal("0.68");
        multiplicacion = diez.multiply(ceroPuntoSesentaYOcho);
        System.out.println( multiplicacion );
        BigDecimal ceroPuntoSesentaYNueve = new BigDecimal("0.69");
        multiplicacion = diez.multiply(ceroPuntoSesentaYNueve);
        System.out.println( multiplicacion );
    }
}

La salida es :

0.2
0.3
6.70
6.80
6.90

Y, de hecho, en tu ejemplo el ordenador no está calculando incorrectamente la suma. Lo que está haciendo el ordenador es lo que hace siempre : Hacer lo que le has dicho, ESTRICTAMENTE, lo cual no tiene por qué ser lo que tu quieres que haga.

Cuando haces 0.1+0.2 parece que le pides que sume 0.1 a 0.2, cuyo resultado debiera ser 0.3
Pero no es así. Lo que en realidad le has dicho al ordenador que haga es :
Interpreta y ejecuta la expresión contenida en la cadena de caracteres "0.1+0.2"

Lo cual conlleva las siguientes acciones :

  • Análisis lexicográfico que divide la cadena en 3 símbolos(tokens) : 0.1 , + y 0.2
  • Análisis sintáctico que, por ejemplo (puede ser de muchas formas), crea una estructura de árbol sintáctico:
    arbol sintáctico

  • Análisis semántico que convierte 0.1 al valor más cercano que es representable con el tipo de datos elegido, en este caso el implícito. Y lo mismo con 0.2 . Aquí está una fuente de error. El programa no va a manejar el valor 0.1 sino aquel más cercano que es representable en el tipo de datos elegido, que en javascript es doble precisión tal y como se especifica en standard IEEE 754. Y en ese formato 0.1 no es posible representarlo exáctamente, con lo que hay un pequeño error.

  • Ejecución. Que suma los dos valores y convierte el resultado al más cercano que es representable. Esto es otra fuente de errores.
  • Impresión. Imprimir una representación visual del valor de suma obtenido. Puede ocurrir que el resultado sea correcto (por ejemplo 0.125+0.125=0.25) pero que por el formato de impresión elegido se impriman menos decimales (0.2) . En este caso el ordenador ha calculado la solución exacta pero ha mostrado una aproximación. Y también puede ocurrir que el resultado sea inexacto (por ejemplo 0.1+0.2=0.30000000000000004) pero que por el formato de impresión elegido se omitan decimales dando apariencia de resultado exacto (.3) pese a que el valor de suma almacenado en el ordenador sea ligeramente inexacto.

Conclusiones

Es posible hacer cálculos exactos en un ordenador. Hay programas y lenguajes específicos para ello.
En los lenguajes de programación de propósito general, como C++, Java o Javascript, se hacen cálculos aproximados por defecto, por cuestiones de rendimiento y porque es suficiente para múltiples aplicaciones. En estos lenguajes también es posible hacer cálculos exactos pero hay que utilizar las librerías y/o elementos del lenguaje apropiados.

Anonymous Coward
  • 6,185
  • 4
  • 31
  • 58
35

Perl6 entiende los números porque trata los números como fracciones (ratios) (> es un "prompt" o símbolo del sistema para la línea de comandos):

perl6
> 0.1 + 0.1
0.2
> 0.1 + 0.2
0.3
> 10 * 0.67
6.7
> 10 * 0.68
6.8
> 10 * 0.69
6.9
> (0.1 + 0.5 + 0.55 - 0.15) * 7.00001 - 2 * 0.000005
7

No trata 7.00001 internamente como un numero binario. Lo trata como 700001/100000:

> 7.00001.nude.perl.say
(700001, 100000)

> 0.0000000000000000071.nude.perl.say
(71, 10000000000000000000)

> 0.000000000000000000005.nude.perl.say
(1, 200000000000000000000)

Para tratar con números muy pequeños o muy largas, se debe usar el tipo FatRat (fracción gordo o ratio gordo):

> 0.000000000000000000000000000071.nude.perl.say
(71, 1000000000000000019884624838656)
>my $pequeño = FatRat.new(71,10**30);
0.000000000000000000000000000071
> $pequeño + 1
1.000000000000000000000000000071
> $pequeño * 10
0.00000000000000000000000000071
> my $pequeño_al_cuadrado = $pequeño*$pequeño;
0.000000000000000000000000000000000000000000000000000000005041
> 1 + $pequeño_al_cuadrado
1.000000000000000000000000000000000000000000000000000000005041

Respuesta inspirado por Ovid.

Gracias a Christoph de StackOverflow por informarme sobre el FatRat.


Se dice que hay 10 tipos de personas: los que piensan como un ordenador (una computadora) y los que piensan como un humano. Me gusta Perl 6 porque me permite pensar mas como un humano.

34

¿Por qué al sumar mis números, como 99.92 + 0.04, en vez de dar 99.96 da un resultado extraño como 99.96000000000001?

Porque internamente, los ordenadores usan un formato (punto flotante binario) que no puede representar de forma precisa números como 0.1, 0.2 o 0.3 de ninguna manera.

Cuando el código es compilado o interpretado, tu “0.1” se redondea al número más cercano en ese formato, lo que resulta en un pequeño error de redondeo incluso antes de que se haga la operación.

¿Por qué los ordenadores usan un sistema tan estúpido?

No es estúpido, solo diferente. Los números decimales no pueden representar con precisión un número como ⅓, así que lo tienes que redondear a algo como 0.33 ─ y no esperas que 0.33 + 0.33 + 0.33 sea igual a 1 tampoco, ¿no?

Los ordenadores usan números binarios porque son más rápidos de manejar, y porque para la mayoría de operaciones un error en la 17ª cifra decimal no importa en absoluto ya que los valores con los que trabajas no eran así de precisos de todas formas.

¿Qué puedo hacer para evitar este problema?

Eso depende del tipo de cálculos que estés haciendo.

  • Si de verdad necesitas que tus resultados se sumen con exactitud, especialmente cuando trabajas con dinero: utiliza un tipo de datos decimal especial.
  • Si es solo que no quieres ver todos esos decimales extra: simplemente da formato a tu resultado redondeando a un número fijo de cifras decimales cuando lo presentes.
  • Si no tienes un tipo de datos decimal, una alternativa es trabajar con enteros, e.g. hacer todos los cálculos con dinero en céntimos. Pero esto requiere más trabajo y tiene algunas desventajas.

¿Por qué otros cálculos como 0.1 + 0.4 sí funcionan bien?

En este caso, el resultado (0.5) puede ser representado de manera exacta como un número de punto flotante, y es posible que los errores de redondeo de los datos de partida se cancelen entre sí ─ aunque no se debería confiar excesivamente en esto (e.g. cuando esos dos números fueron almacenados en representaciones de punto flotante de diferente tamaño, los errores de redondeo pueden no cancelarse entre ellos).

En otros casos como 0.1 + 0.3, el resultado no es realmente 0.4, pero está lo suficientemente cerca como para que 0.4 sea el número más corto que está más cerca del resultado que cualquier otro número de punto flotante. La mayoría de lenguajes presentan ese número en vez de convertir el resultado real a una fracción decimal.

Si quieres más información, puedes acudir a las Referencias.

Fuente: puntoflotante.org

Black Sheep
  • 13,096
  • 6
  • 36
  • 60
29

El problema es que usando una base binaria, esas cifras no se pueden representar con exactitud. Es como si intentas representar 2/3 en el sistema decimal, no se puede, ya que tendrías que repetir un 6 de manera infinita en el último decimal, por lo que usamos un aproximado.

mornaner
  • 399
  • 3
  • 4
  • 8
    Esto no es del todo cierto, es posible representar 1/3 o 2/3 de manera exacta usando [notación periódica](https://es.wikipedia.org/wiki/N%C3%BAmero_decimal#N.C3.BAmero_decimal_peri.C3.B3dico). Esto es aplicable en general para cualquier número racional en cualquier base, incluyendo binario. El estándar IEEE 754 simplemente no contempla este caso, y por tanto no permite representar este tipo de cantidades de forma exacta. – Darkhogg Dec 04 '15 at 07:45
27

Tu pregunta es un caso específico de un tema mayor. Puedes leer el resumen de análisis numérico aquí. Es de un punto de vista de la matemática. Del punto de vista de la informática puedes leer aquí.

Pero el lenguaje sí importa porque diferentes lenguajes van a usar diferentes aproximaciones a los números continuos, y van a redondear los resultados de una manera diferente. Aquí hay un ejemplo.

PS>10*0.68
6.8
PS>(10*0.68).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Double                                   System.ValueType


PS>[single]$a = 10*0.68
PS>$a
6.8
PS>$a.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Single                                   System.ValueType


PS>[math]::pi
3.14159265358979
PS>([math]::pi).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Double                                   System.ValueType

Powershell usa double en cálculos con fracciones, por default, como se hizo en el primer ejemplo.

Aún si se le obliga a usar single, como en el segundo ejemplo, el resultado se presenta correctamente. Pero esto puede ser porque hizo el redondeo de tal modo que no se ve el error.

El tercer ejemplo da un número pi, que no se puede representar exactamente en powershell. Es una aproximación aunque una aproximación muy cercana. Si se fuera a hacer millones de cálculos basados en esta aproximación los resultados podrían ser basura.

Powershell es un interfaz entre el usario y .NET. Yo no he investigado cuales de estos cálculos son cuestión de Powershell y cuales de .NET.

Walter Mitty
  • 451
  • 3
  • 7
21

En Javascript, puedes utilizar el método toFixed(). El cual te transforma en una string el número y luego recorta según el número de decimales que le hayas pasado.

var num = 0.1 + 0.2;
// 0.30000000000000004
console.log(num.toFixed(2));
// 0.30
eugenio
  • 550
  • 2
  • 8
  • 4
    Esto no hace que el cálculo sea correcto, simplemente está formateando el resultado (ver https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed). – astrojuanlu Dec 02 '15 at 09:01
  • 1
    Es cierto muchas veces funciona pero no es lo recomendado especialmente en software financiero, la mayoría de lenguajes tiene una implementación de BigDecimal destinado para operaciones exactas de este tipo. – Joel Ibaceta Dec 02 '15 at 16:33
  • No, esto no funciona, solo oculta el error de precisión. Los cálculos se siguen realizando igual que en el primer caso. *-1* porque no responde a la pregunta, ni siquiera incluye una explicación y porque la "solución" es para un lenguaje concreto. – Darkhogg Dec 04 '15 at 07:57
21

Como ya explicaron en algunos comentarios esto se debe a como los ordenadores almacenan y obtienen números de punto flotante, lo cual trae muchos problemas especialmente en aplicaciones que requieren alta precision por lo que existe un tipo de dato que ofrece la posibilidad de trabajar con cálculos mas exactos, puede llamarse distinto en otros lenguajes te dejo la especificación en Ruby y Java.

http://ruby-doc.org/stdlib-1.9.3/libdoc/bigdecimal/rdoc/BigDecimal.html http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html

Joel Ibaceta
  • 2,333
  • 10
  • 34
18

En informática, los cálculos no suelen ser exactos: sólo precisos. Lo que te molesta de los resultados no es su falta de precisión -que es mucha- sino que no te los suministran en el formato que deseas. Buscas una función que transforme los datos numéricos en una cadena que tenga el formato que te guste. En Visual Basic, esa función se llama "Format". A veces es preferible 3.00 antes que 2.99999999. En ese caso, debes recurrir a alguna función de redondeo antes de aplicar el formato.

  • 1
    Hola y bienvenido. Esto no proporciona una respuesta mejor a todas las que están ya escritas. Cuando tengas suficiente reputación, podas comentar y pedir mas información sobre las preguntas y respuestas. Bienvenido y sigue intentándolo! – gbianchi Aug 14 '17 at 00:04
13

Eso es porque Javascript se basa en el estándar “IEEE 754” también llamado punto flotante.

En resumen, 0.1 + 0.2 en estándar “IEEE 754” el resultado no es exacto, se acerca bastante
0.30000000000000004, pero si no es exacto, no nos sirve de nada si queremos hacer una comparación (por ejemplo 0.1 + 0.2 = 0.3)

una práctica común es usar un pequeño margen de error, ese valor usado como estándar en la industria se llama “epsilon de la máquina” su valor en javascript es 2^-52 (2.220446049250313e-16)

a partir de ES6 Number.EPSILON nos provee con este valor para usarse en este tipo de casos

Si no cuentas con ES6 en tu entorno, puedes hacer un polyfill muy fácilmente

if (!Number.EPSILON) {
    Number.EPSILON = Math.pow(2,-52);
}

te dejo un ejemplo de cómo comparar 2 números usando Number.EPSILON

function numbersCloseEnoughToEqual(n1,n2) {
    return Math.abs( n1 - n2 ) < Number.EPSILON;
}

var a = 0.1 + 0.2;
var b = 0.3;

numbersCloseEnoughToEqual( a, b );                  // true
numbersCloseEnoughToEqual( 0.0000001, 0.0000002 );  // false

Te recomiendo este capítulo de You dont know javascript donde explican de manera muy sencilla el porqué las operaciones no son exactas en lenguajes que usan el estándar IEEE 754.

(aquí verás el mismo ejemplo aplicado pero más detallado y con más información sobre los valores numéricos) 
 https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch2.md

  • [Aquí](https://stackoverflow.com/questions/19141432/python-numpy-machine-epsilon) dicen como saber el epsilon de la máquina en python, ¿Cómo se haria para hacerlo en Javascript? – Boris Valderrama Jan 01 '19 at 09:39
  • A partir de ES6 podemos usar Number.EPSILON; el valor retornado en la consola es 2.220446049250313e-16 //console.log(Number.EPSILON) En base a ese valor, puedes hacer tus cálculos, a eso te referías? o hay algo en tu pregunta que no esté tomando en cuenta @ElPasta – Israel Ortiz Cortés Jan 02 '19 at 18:28
12

Según lo que comentas ese código está escrito en JavaScript. Basandonos en ello, la forma correcta de realizar operaciones aritméticas es utilizando los métodos parse y toFixed.

Si quieres sumar dos números con decimales debes hacerlo de esta manera.

var sumar = function(){
  var $lado = 0.3,
      $altura = 3.1,
      $total = 0.0;
    
    //Operas las sumas para sacar el total
    $total = parseFloat($lado) + parseFloat($altura);
    
    console.log($total);
}

sumar();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Por el contrario, si lo que quieres sumar son dos enteros debes hacerlo con el método parseInt(). Te dejo un ejemplo.

var sumar = function(){
  var $lado = 3,
      $altura = 4,
      $total = 0;
    
    //Operas las sumas para sacar el total
    $total = parseInt($lado) + parseInt($altura);
    
    console.log($total);
}

sumar();

Ten en cuenta que puedes usar parseInt o parseFloat, dependiendo de qué tipo de dato estés utilizando.

Ahora bien, tomando como ejemplo el segundo escenario que planteas, para este problema existe el método toFixed(). Este toma los decimales que le indices dentro del paréntesis, es decir que, si colocas dos, te tomará 0.30, según el escenario mencionado anteriormente.

Te dejo un ejemplo de esto.

var sumar = function(){
  var $lado = 0.1,
      $altura = 0.2,
      $total = 0.0;
    
    //Toma un decimal
    $total = (parseFloat($lado) + parseFloat($altura)).toFixed(1);
    console.log($total);
        
    //Toma dos decimales
    $total = (parseFloat($lado) + parseFloat($altura)).toFixed(2);
    console.log($total);
        
    //Toma tres decimales
    $total = (parseFloat($lado) + parseFloat($altura)).toFixed(3);
    console.log($total);
}

sumar();

Espero te sirva. Suerte en tus próximos desarrollos.

Angel Cabrera
  • 141
  • 1
  • 4