Recently, I am learning about the electron ic framework, and I want to use this framework to make a simple calculator demo. When I was calculating decimals, I found a problem.
0.1+0.2=?
The output is 0.30000000000004.
Why?
In fact, for the four operations of floating point numbers, almost all programming languages will have similar accuracy error problems, but in C++/C#/Java these languages have been packaged to avoid accuracy problems, while JavaScript is a weak type of language, from the design idea there is no strict data type for floating point numbers, so the problem of accuracy error. It is particularly prominent.
First, let's analyze why this accuracy error occurs.
First of all, we should think about the seemingly pediatric problem of 0.1 + 0.2 from the perspective of computer. We know that binary, not decimal, can be read by computers, so let's first convert 0.1 and 0.2 into binary.
0.1 = > 0.0001 1001 1001 1001. (infinite cycle)
0.2 = > 0.0011 0011 0011.. (infinite cycle)
We find that 0.1 and 0.2 are converted to binary and become an infinite loop number. In real life, infinite loop can be understood, but computers do not allow infinite loop. For infinite loop decimals, the computer rounds. The decimal part of a double-precision floating-point number can support 52 bits at most, so when the two are added together, a string of binary digits truncated by the restriction of floating-point decimal digits is obtained. At this time, we convert it to decimal, and it becomes 0.30000000000000000004.
Knowing the causes of floating-point numbers, how to deal with this problem?
Method 1: Keep decimal by toFixed(num) method. Because this method is based on rounding to retain decimal, the final calculation results are not accurate.
Method 2: The number to be calculated is upgraded (multiplied by 10 n power) into integers that can be accurately recognized by the computer, and then downgraded. This method is recommended. Specific code is as follows (mainly three methods):
/*Determine whether obj is an integer*/
function isInteger(obj){
return Math.floor(obj) === obj;
}
/**
* Converts a floating point number to an integer, returning integers and multiples
* For example, in 3.14, 314 times is 100
*
*/
function toInteger(floatNum){
var ret = {times:1,num:0};
//It's an integer.
if(isInteger(floatNum)){
ret.num = floatNum;
return ret;
}
var strfi = floatNum + '';
//Find subscripts for decimal points
var dotPos = strfi.indexOf('.');
console.log('dotPos===='+dotPos);
//Get the number of decimal digits
var len = strfi.substr(dotPos+1).length;
console.log('len===='+len);
//Math.pow(10,len) specifies the len power of 10.
var time = Math.pow(10,len);
//Converting Floating Points to Integers
var intNum = parseInt(floatNum*time + 0.5,10);
console.log('intNum===='+intNum);
ret.times = time;
ret.num = intNum;
return ret;
}
/**
*Carry out operations
*The three parameters are the two numbers and operators to be operated on respectively.
*/
function operation(a,b,op){
var o1 = toInteger(a);
var o2 = toInteger(b);
var n1 = o1.num;
var n2 = o2.num;
var t1 = o1.times;
var t2 = o2.times;
var max = t1 > t2 ? t1 : t2;
var result = null;
switch(op){
case 'add':
if(t1 === t2){
result = n1 + n2;
}else if(t1 > t2){
result = n1 + n2 * (t1/t2);
}else{
result = n1 * (t2/t1) + n2;
}
return result / max;
break;
case 'subtract':
if(t1 === t2){
result = n1 - n2;
}else if(t1 > t2){
result = n1 - n2 * (t1/t2);
}else{
result = n1 * (t2/t1) - n2;
}
return result / max;
break;
case 'multiply':
result = (n1 * n2)/(t1 * t2);
return result;
break;
case 'divide':
result = (n1 / n2)/(t2 / t1);
return result;
break;
}
}