multiplicar - parsefloat javascript 2 decimales
¿Cómo multiplicar en Javascript? problemas con decimales (13)
Tengo el siguiente código en Javascript:
var m1 = 2232.00;
var percent = (10/100);
var total = percent*m1;
alert(total);
El problema es que la variable "total" me da "223.20000000000002" y debería ser "223.2", ¿qué debo hacer para obtener el valor correcto?
Aquí hay una solución alternativa para la multiplicación de números flotantes. Es bastante simple pero funciona para mí. Calculas cuántos decimales tienen los números con esta función.
function decimalPlaces(num) {
var match = (''''+num).match(/(?:/.(/d+))?(?:[eE]([+-]?/d+))?$/);
if (!match) { return 0; }
return Math.max(
0,
// Number of digits right of decimal point.
(match[1] ? match[1].length : 0)
// Adjust for scientific notation.
- (match[2] ? +match[2] : 0));
}
Y luego para tu respuesta final "total" lo haces
total = total.toFixed(decimalPlaces(a)+decimalPlaces(b));
donde a, b son tus numeros
El operador "*" y "/" no funcionan perfectamente siempre, por ejemplo:
32.09 * 100 = 3209.0000000000005
100 / (1 / 32.09) = 3209.0000000000005
Solución:
Una solución, la más fácil, tener decimales es usar .toFixed (2) donde "2" es el número de dígitos decimales que desea. Pero debes tener en cuenta que esto te devuelve una Cadena y redondea el valor.
45.6789.toFixed(2) —> "45.68" as String
Otra opción, la más completa, es usar .toLocaleString que convierte el número correctamente al código de país que desea. Puede configurar un par de parámetros para fijar los valores decimales siempre a 2. Esto también le devuelve una Cadena:
(654.3453).toLocaleString(
''en-US'',
{minimumFractionDigits: 2, maximumFractionDigits: 2},
) —> "654.35" as String
Si lo necesita como un Número, puede envolverlo en Número (...):
Number((654.3453).toLocaleString(
''en-US'',
{minimumFractionDigits: 2, maximumFractionDigits: 2},
)) —> 654.35 as Number
Si solo desea un número sin decimal, use uno de estos métodos para asegurarse de que el resultado sea sin decimales.
Math.trunc(32.09); —> 32 as Number
(32.09).toFixed(0); —> “32” as String
32.09 | 0; —> 32 as Number
Encontré la respuesta en las siguientes páginas, gracias a Dimitry :
Hoja de trucos de punto flotante para JavaScript
Decidí usar las siguientes clases porque necesito los valores exactos de las operaciones y están relacionadas con las operaciones de dinero:
Esto se puede hacer bien con una biblioteca externa llamada decimal.js que proporciona un tipo Decimal
para JavaScript. También está disponible para el nodo en npm. A continuación se muestra un ejemplo que reproduce el ejemplo original de gustavomanolo usando decimal.js.
// Decimal type provided by decimal.js (http://mikemcl.github.io/decimal.js/)
var m1 = new Decimal( 2232.00 );
var percent = new Decimal( 10/100 );
var total = m1.mul(percent);
console.log( ''Total:'', total );
<script src="https://cdnjs.cloudflare.com/ajax/libs/decimal.js/7.2.3/decimal.min.js"></script>
He encontrado una solución muy simple. El operador *
está un poco roto cuando se trata de números decimales, pero el operador /
no lo está. Una multiplicación se puede transformar fácilmente en una división ya que a • b = a / (1 / b)
function times(a, b) { return a/(1/b) }
Simplemente reemplace el percent * m1
con los times(percent, m1)
.
Actualización: No funciona todas las veces.
No se puede obtener el valor exacto. Este es el problema fundamental con los números de punto flotante.
Puede forzar un número fijo de números decimales con toFixed
:
alert(total.toFixed(2));
Sin embargo, tenga en cuenta que esto dejará ceros finales, lo que tal vez no desee. Puede eliminarlos con .replace(/0+$/,'''');
Podrías hacerlo
var total = +(percent*m1).toPrecision(15);
223.2 === total; // true
223.2 === 0.1*2232.00; // false
Sólo inténtalo
var x = 0.07;
console.log((x+1)*100 - 100);
ahora, reemplaza el valor de x para los otros valores ;-)
Si está intentando mostrar este número, puede convertirlo a una cadena toFixed(1) . Si haces esto, mantén un registro de los tipos porque no puedes multiplicar la cadena por otro número.
Si lo va a utilizar en otro cálculo, podría truncarlo a un decimal:
Math.round( total * 10 ) / 10
Sin embargo, como lo señalaron varias personas, el valor inexacto es la forma en que lo son los números en coma flotante.
Ver las preguntas vinculadas en los comentarios para más información buena.
Si estás usando Angular, hice un componente para esto.
Instalar con la glorieta
bower install angular-floating-point --save
Uso
var pretty = floatingPoint.makePretty(6.1*6);
Aquí hay una demostración -> https://mattspaulding.github.io/angular-floating-point
Aquí está la fuente -> https://github.com/mattspaulding/angular-floating-point
Pruébelo usted mismo con este fragmento de código a continuación.
angular.module(''myApp'', [''floatingPoint''])
.controller(''myCtrl'', function ($scope, floatingPoint) {
$scope.calculate = function () {
$scope.result =$scope.num0*$scope.num1;
$scope.prettyResult=floatingPoint.makePretty($scope.result)
}
$scope.num0=6.1;
$scope.num1=6;
$scope.calculate();
});
<html>
<head>
<title>My Angular App</title>
<script src=''//code.jquery.com/jquery-latest.min.js''></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="https://rawgit.com/mattspaulding/angular-floating-point/master/dist/angular-floating-point.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<div class="row" style="padding-top: 10px;text-align:center">
<label>(try me) ==> </label>
<input ng-model="num0" ng-change="calculate()" style="width:100px; height:30px">
X
<input ng-model="num1" ng-change="calculate()" style="width:100px; height:30px">
</div>
<div class="row" style="padding-top: 50px;">
<div class="col-xs-6">
<label style="float: right;">Ugly calculation:</label>
</div>
<div class="col-xs-6">
<label style="float: left;">{{result}}</label>
</div>
</div>
<div class="row" style="padding-top: 20px;">
<div class="col-xs-6">
<label style="float: right;"><span style="color:blue">Angular Floating Point</span> calculation:</label>
</div>
<div class="col-xs-6">
<label style="float: left;">{{prettyResult}}</label>
</div>
</div>
</body>
Terminé con la siguiente solución:
function decimalmultiply(a, b) {
return parseFloat((a * b).toFixed(12));
}
10.50*30.45=319.72499999999997
decimalmultiply(10.50,30.45)=319.725
Este método devuelve un número , no una cadena , sin truncar decimales significativos (hasta 12).
total.toFixed(2)
puede ayudar. Pero tenga en cuenta que la variable total
será tipificada en una cadena.
.toFixed () es la mejor solución. Solo se mantendrán dos dígitos después del punto.
Exp 1:
var value = 3.666;
value.toFixed(2); //Output : 3.67
Exp 2:
var value = 3.0000;
value.toFixed(2); //Output : 3.00