当前位置:网站首页>JS addition and multiplication error resolution number precision
JS addition and multiplication error resolution number precision
2022-06-11 11:41:00 【Michael18811380328】
JS Addition and multiplication error resolution number-precision
Problem description
In a project , Need to compute 0.56 * 100 Then convert it into a string , Result calculation error , So the research uses this library to realize .
But calculation 0.59 * 100 Results the correct . This is a JS Internal problems .
Of course, there are classic 0.1 + 0.2 = 0.30000000000000004 problem


I use number-precision This library , Can achieve JS Precise four operations .
install
npm install number-precision --saveThe main method
You can calculate addition, subtraction, multiplication and division (plus,minus,times, divides) And find the approximate value (strip, round)
NP.strip(num) // strip a number to nearest right number
NP.plus(num1, num2, num3, ...) // addition, num + num2 + num3, two numbers is required at least.
NP.minus(num1, num2, num3, ...) // subtraction, num1 - num2 - num3
NP.times(num1, num2, num3, ...) // multiplication, num1 * num2 * num3
NP.divide(num1, num2, num3, ...) // division, num1 / num2 / num3
NP.round(num, ratio) // round a number based on ratioSpecific use
import NP from 'number-precision';
NP.strip(0.09999999999999998); // = 0.1
NP.plus(0.1, 0.2); // = 0.3, not 0.30000000000000004
NP.plus(2.3, 2.4); // = 4.7, not 4.699999999999999
NP.minus(1.0, 0.9); // = 0.1, not 0.09999999999999998
NP.times(3, 0.3); // = 0.9, not 0.8999999999999999
NP.times(0.362, 100); // = 36.2, not 36.199999999999996
NP.divide(1.21, 1.1); // = 1.1, not 1.0999999999999999
NP.round(0.105, 2); // = 0.11, not 0.1If you want to avoid the following warnings ( Report errors : Numeric conversion integer out of bounds , Inaccurate results ), You can add the following prompt at the beginning of the document
PS: If you want to get rid of XXX is beyond boundary when transfer to integer, the results may not be accurate, use this at the beginning of your app to turn off boundary checking.
NP.enableBoundaryChecking(false); // default param is true
The text has ended , The following is a simple source code analysis , Let's see how the author achieves accurate calculation .
Source code analysis
Use here TS Achieve accurate calculation .
type numType = number | string;
/**
* @desc Solve the floating operation problem , Avoid the loss of multiple digits and calculation accuracy after the decimal point .
* Sample questions :2.3 + 2.4 = 4.699999999999999,1.0 - 0.9 = 0.09999999999999998
*/
/**
* Turn the wrong data into positive
* strip(0.09999999999999998)=0.1
*/
function strip(num: numType, precision = 15): number {
return +parseFloat(Number(num).toPrecision(precision));
}
/**
* Return digits length of a number
* @param {*number} num Input number
*/
function digitLength(num: numType): number {
// Get digit length of e
const eSplit = num.toString().split(/[eE]/);
const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
return len > 0 ? len : 0;
}
/**
* Turn a decimal into an integer , Support scientific counting . If the decimal is an integer
* @param {*number} num Enter the number
*/
function float2Fixed(num: numType): number {
if (num.toString().indexOf('e') === -1) {
return Number(num.toString().replace('.', ''));
}
const dLen = digitLength(num);
return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
}
/**
* Check whether the number is out of bounds , If you cross the line, give a hint
* @param {*number} num Enter the number
*/
function checkBoundary(num: number) {
if (_boundaryCheckingState) {
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
console.warn(`${num} is beyond boundary when transfer to integer, the results may not be accurate`);
}
}
}
/**
* Exact multiplication
*/
function times(num1: numType, num2: numType, ...others: numType[]): number {
if (others.length > 0) {
return times(times(num1, num2), others[0], ...others.slice(1));
}
const num1Changed = float2Fixed(num1);
const num2Changed = float2Fixed(num2);
const baseNum = digitLength(num1) + digitLength(num2);
const leftValue = num1Changed * num2Changed;
checkBoundary(leftValue);
return leftValue / Math.pow(10, baseNum);
}
/**
* Add exactly
*/
function plus(num1: numType, num2: numType, ...others: numType[]): number {
if (others.length > 0) {
return plus(plus(num1, num2), others[0], ...others.slice(1));
}
const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
}
/**
* Exact subtraction
*/
function minus(num1: numType, num2: numType, ...others: numType[]): number {
if (others.length > 0) {
return minus(minus(num1, num2), others[0], ...others.slice(1));
}
const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
}
/**
* Exact division
*/
function divide(num1: numType, num2: numType, ...others: numType[]): number {
if (others.length > 0) {
return divide(divide(num1, num2), others[0], ...others.slice(1));
}
const num1Changed = float2Fixed(num1);
const num2Changed = float2Fixed(num2);
checkBoundary(num1Changed);
checkBoundary(num2Changed);
// fix: similar 10 ** -4 by 0.00009999999999999999,strip correct
return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
}
/**
* rounding
*/
function round(num: numType, ratio: number): number {
const base = Math.pow(10, ratio);
return divide(Math.round(times(num, base)), base);
}
let _boundaryCheckingState = true;
/**
* Whether boundary check is carried out , Default on
* @param flag Marker switch ,true For opening ,false To close , The default is true
*/
// Here you can set the boundary check ( The default is true)
function enableBoundaryChecking(flag = true) {
_boundaryCheckingState = flag;
}
// Output the above method
export { strip, plus, minus, times, divide, round, digitLength, float2Fixed, enableBoundaryChecking };
export default {
strip,
plus,
minus,
times,
divide,
round,
digitLength,
float2Fixed,
enableBoundaryChecking,
};
Reference link
https://developer.aliyun.com/mirror/npm/package/number-precision
边栏推荐
- ELK - ElastAlert最大的坑
- Lifeifei: I am more like a scientist in physics than an engineer
- Dominating set, independent set, covering set
- WordPress站内链接修改插件:Velvet Blues Update URLs
- [file upload vulnerability 06] server file content detection and bypass experiment + image horse production method (based on upload-labs-14 shooting range)
- JS prototype. The find () method has no effect on the object array. It is urgent...
- 17.5 concept, usage, deadlock demonstration and solution of mutex
- 李飞飞:我更像物理学界的科学家,而不是工程师|深度学习崛起十年
- WordPress landing page beautification plug-in: recommended by login Designer
- Command mode - attack, secret weapon
猜你喜欢

ELK - ElastAlert最大的坑

再不刷题就晚了,最全的BAT大厂面试题整理

Use yolov3 to train yourself to make datasets and get started quickly

01_ Description object_ Class diagram

苹果MobileOne: 移动端仅需1ms的高性能骨干

Node连接MySql数据库写模糊查询接口

How to solve the problem that high-precision positioning technologies such as ultra wideband UWB, Bluetooth AOA and RTK cannot be widely used due to their high cost? Adopt the idea of integrated deplo

JS prototype. The find () method has no effect on the object array. It is urgent...

The complete manual of the strongest Flink operator is a good choice for the interview~

设置默认收货地址【项目 商城】
随机推荐
Introduction to database system - Chapter 2 - relational database (2.1~2.3) (important knowledge points)
JEST 单元测试说明 config.json
Uncaught TypeError: Cannot set property ‘next‘ of undefined 报错解决
The complete manual of the strongest Flink operator is a good choice for the interview~
找到自己的优势,才能干活不累,事半功倍!
my. Binlog startup failure caused by the difference between [mysql] and [mysqld] in CNF
广东市政安全施工资料管理软件2022新表格来啦
WordPress regenerate featured image plugin: regenerate thumbnails
Adapter mode -- can you talk well?
Where is it safer to open an account for soda ash futures? How much capital is needed to trade soda ash futures at present?
WordPress重新生成特色图像插件:Regenerate Thumbnails
收货地址列表展示【项目 商城】
在毕设中学习02——numpy多维数组的切片,形态变化,维度交换
【C语言】anonymous/unnamed struct&&union
浙大联合微软亚研院发布视频识别新方法,可对视频逐帧识别且无需,数据标记,或可用于手语翻译等
National multi-year solar radiation spatial distribution data 1981-2022, temperature distribution data, evapotranspiration data, evaporation data, rainfall distribution data, sunshine data, wind speed
Problems encountered when using nailing intranet to penetrate and upload PHP projects
Hamiltonian graph
[fragmentary thoughts] thoughts on wavelength, wave velocity and period
202年最新热门收益较高的年金险产品是什么?