cause
A question was asked yesterday:
Because of the JS accuracy problem0.1 + 0.2 == 0.30000000000000004
, is it possible to get a correct value?0.1 + 0.2 == 0.3
It's simple, turn it into an integer, and then divide it back. Or round up and keep decimals.
((0.1 + 0.2) * 10).toFixed()/10
(0.1 * 10 + 0.2 * 10)/10
Then I was asked again, what if I am two decimal places? What about the three? Let me say you have no savvy! In the same way, you add it and you are done. Then he was in a hurry, what about thirty people?
The question then changes, and it becomes JS can save such a number .
I think, it is not that large numbers computing it, I brush off. For simplicity, I found a library bignumber to implement this part of the logicnew BigNumber(0.1).plus(0.2)
simple batch.
But here I myself: I need to follow a specific way of writing , which is unreasonable. I thought about it again, I used the calculator before, and it will give you the input of '1+2+3*4'
and then let you output the calculation results (although there is a lazy 061ca538eed7fd solution, but it eval
Just say the whole thing, check it: 🐶 depressed
- Question one, only supports addition and subtraction
- Question two, support brackets, do not support multiplication and division
- Question three, gradually perverted . It's not mathematics at all. It's a set of own logic.
- Question four, encryption, you need to open a membership.
No way, failed (tongxin), writing by yourself is too time-consuming, look at the solution to get a keyword reverse Polish formula , can handle the calculation of priority.
The expression is converted to inverse Polish
This has to complain about the garbage resources on the Internet
- actually does not support decimals
- Actually only supports singles
- The output is also problematic
- The search results are on the first screen
- Actually the previous page is the same article
Fortunately, the calculation of integers is no problem. We are doing a while where we get the number to ensure completeness.
function calculator(str) {
let n = 0, charStack = [], numStack = [], reducerStr = [], leftIndex = -1
const op = {
'+' : 1,
'-' : 1,
'*' : 2,
'/' : 2,
'(' : 3,
')' : 3
}
while(n < str.length) {
const byte = str[n]
// 数字
// if(/\d/.test(byte)) {
if(/[\d\.]+/.test(byte)) {
// reducerStr.push(byte)
let result = byte;
let _str = str[n+1]
while(/[\d\.]+/.test(_str)){
result+=_str;
n++;
_str = str[n+1]
}
reducerStr.push(result)
} else if(/\(|\)/.test(byte)) {
// 左括号入栈
if(byte === '(') {
charStack.push(byte)
leftIndex = n
// console.log('左括号', byte)
// 右括号出栈
} else {
let nowChar = charStack.pop()
while(nowChar && nowChar !== '(') {
reducerStr.push(nowChar)
nowChar = charStack.pop()
}
}
// 符号
} else {
// 字符栈顶元素
let nowChar = charStack[charStack.length - 1]
while(nowChar && op[byte] < op[nowChar] && nowChar !== '(') {
charStack.pop()
reducerStr.push(nowChar)
nowChar = charStack[charStack.length - 1]
}
charStack.push(byte)
}
n++
}
while(charStack.length) {
reducerStr.push(charStack.pop())
}
return reducerStr
}
Analyze the results of inverse Polish calculations
, it should be a problem solution, he rounded the decimal 161ca538eedb28 convex (艹艹) .
Round off. Then change the calculation location to our library.
var evalRPN = function(tokens) {
const stack = [];
const n = tokens.length;
for (let i = 0; i < n; i++) {
const token = tokens[i];
if (isNumber(token)) {
stack.push((token));
// stack.push(parseInt(token));
} else {
const num2 = stack.pop();
const num1 = stack.pop();
if (token === '+') {
stack.push(new BigNumber(num1).plus(num2));
} else if (token === '-') {
stack.push(new BigNumber(num1).minus(num2));
} else if (token === '*') {
stack.push(new BigNumber(num1).times(num2));
} else if (token === '/') {
stack.push(new BigNumber(num1).dividedBy(num2));
// stack.push(num1 / num2 > 0 ? Math.floor(num1 / num2) : Math.ceil(num1 / num2));
}
}
}
return stack.pop();
};
const isNumber = (token) => {
return !('+' === token || '-' === token || '*' === token || '/' === token );
}
Convenient testing
Here is of course the vue, plus the calculated attributes, it is easy to use.
related resources
- front-end BUG record-what is scientific notation? Here are some accuracy-related information, you can click in to see
- test address: http://jsrun.net/9f9Kp/edit
Reply to the comment section Lao Tie's plan, the plan is feasible.
Add another content related to accuracy.
Math.abs(0.1+0.2 - 0.3) < Number.EPSILON
Math.abs(0.1+0.2 - 0.3000000000000001) < Number.EPSILON
Math.abs(0.1+0.2 - 0.300000000000001) < Number.EPSILON
The value of the EPSILON attribute is close to 2.2204460492503130808472633361816E-16, or 2-52.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。