可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
i've the following code in Javascript:
var m1 = 2232.00;
var percent = (10/100);
var total = percent*m1;
alert(total);
The problem is that the variable "total" gives me "223.20000000000002" and it should be "223.2", what should i do to get the correct value?
回答1:
.toFixed() is best solution.It will keep only two digits after dot.
Exp 1:
var value = 3.666;
value.toFixed(2); //Output : 3.67
Exp 2:
var value = 3.0000;
value.toFixed(2); //Output : 3.00
回答2:
You can't get the exact value. This is the fundamental problem with floating-point numbers.
You can force a fixed number of decimal numbers with toFixed
:
alert(total.toFixed(2));
However, keep in mind that this will leave trailing zeroes, which you might not want. You can remove them with .replace(/0+$/,'');
回答3:
If you are trying to display this number, you could convert to a string with toFixed(1). If you do this, keep track of the types because you can't then multiply the string with another number.
If you are going to use it in another computation you could truncate it to one decimal place:
Math.round( total * 10 ) / 10
However, as pointed out by various people, the inexact value is just the way floating point numbers are.
See the questions linked in the comments for more good information.
回答4:
I found the answer using the following pages, thanks to Dimitry:
Floating-point cheat sheet for JavaScript
I decided to use the following clases because i need the exact values of the operations and they're related to money operations:
- https://github.com/MikeMcl/big.js
- https://github.com/MikeMcl/bignumber.js/
回答5:
The operator "*" and "/" do not work perfectly always, for example:
32.09 * 100 = 3209.0000000000005
100 / (1 / 32.09) = 3209.0000000000005
Solution:
One solution, the easy one, to have decimals is useing .toFixed(2) where "2" is the number of decimal digits that you want. But you have to take into account this return you a String, and it rounds the value.
45.6789.toFixed(2) —> "45.68" as String
Other option, the most complete, is using .toLocaleString that converts the number properly to the country code that you want. You can set a pair of params to fix the decimals values always to 2. This also returns you a String:
(654.3453).toLocaleString(
'en-US',
{minimumFractionDigits: 2, maximumFractionDigits: 2},
) —> "654.35" as String
If you need it as a Number, you can wrap it into Number( ... ) :
Number((654.3453).toLocaleString(
'en-US',
{minimumFractionDigits: 2, maximumFractionDigits: 2},
)) —> 654.35 as Number
If you only want a no decimal number, use one of this methods to be sure that the result is without decimals.
Math.trunc(32.09); —> 32 as Number
(32.09).toFixed(0); —> “32” as String
32.09 | 0; —> 32 as Number
回答6:
This can be done well with an external library called decimal.js that provides a Decimal
type for JavaScript. It's also available for Node on npm. Below is an example that replicates the original example from gustavomanolo using 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>
回答7:
Here is a work around solution for multiplication of floating numbers. It's pretty simple but works for me. You figure out how many decimals the numbers have with this function.
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));
}
And then for your final answer "total" you do
total = total.toFixed(decimalPlaces(a)+decimalPlaces(b));
where a,b are your numbers
回答8:
total.toFixed(2)
may help. But note that the total
variable be will typecasted into a string.
回答9:
Just try
var x = 0.07;
console.log((x+1)*100 - 100);
now, replace the value of x for the other values
;-)
回答10:
I ended up with the following solution:
function decimalmultiply(a, b) {
return parseFloat((a * b).toFixed(12));
}
10.50*30.45=319.72499999999997
decimalmultiply(10.50,30.45)=319.725
This method returns a number, not a string, without truncating significant decimals (up to 12).
回答11:
You could do
var total = +(percent*m1).toPrecision(15);
223.2 === total; // true
223.2 === 0.1*2232.00; // false
回答12:
If you are using Angular, I made a component for this.
Install with bower
bower install angular-floating-point --save
Usage
var pretty = floatingPoint.makePretty(6.1*6);
Here is a demo -> https://mattspaulding.github.io/angular-floating-point
Here is source -> https://github.com/mattspaulding/angular-floating-point
Try it yourself with this snippet below.
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>
回答13:
I found a very simple solution. The *
operator is a bit broken when it comes to decimal numbers, but the /
operator is not. A multiplication can be easily transformed into a division since a • b = a / (1/b)
function times(a, b) { return a/(1/b) }
Just replace percent * m1
with times(percent, m1)
.
Update: It doesn't work all the times.