当前位置:网站首页>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
边栏推荐
- JVM class loading process
- Intl.NumberFormat 设置数字格式
- 2022 | framework for Android interview -- Analysis of the core principles of binder, handler, WMS and AMS!
- 202年最新热门收益较高的年金险产品是什么?
- Runtime reconfiguration of etcd
- arguments.callee 实现函数递归调用
- JS 加法乘法错误解决 number-precision
- Uncaught TypeError: Cannot set property ‘next‘ of undefined 报错解决
- 17.5 concept, usage, deadlock demonstration and solution of mutex
- Only when you find your own advantages can you work tirelessly and get twice the result with half the effort!
猜你喜欢

js中Array.prototype.find() 方法在对象数组上无效果,捉急。。。
![[file upload vulnerability 06] server file content detection and bypass experiment + image horse production method (based on upload-labs-14 shooting range)](/img/30/79516390c2b2b50a224eaa84a0c1c9.jpg)
[file upload vulnerability 06] server file content detection and bypass experiment + image horse production method (based on upload-labs-14 shooting range)
![my.cnf中 [mysql]与[mysqld] 的区别 引起的binlog启动失败的问题](/img/bd/a28e74654c7821b3a9cd9260d2e399.png)
my.cnf中 [mysql]与[mysqld] 的区别 引起的binlog启动失败的问题
![Set the default receiving address [project mall]](/img/eb/2864b124b66d01849315a367948ed4.png)
Set the default receiving address [project mall]

中文输入法输入事件composition的使用

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

找到自己的优势,才能干活不累,事半功倍!

收货地址列表展示【项目 商城】

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

ELK - Hearthbeat实现服务监控
随机推荐
Let WordPress support registered users to upload custom avatars
Intermediate web development engineer, interview questions + Notes + project practice
設置默認收貨地址【項目 商城】
修改 WordPress 管理账号名称插件:Admin renamer extended
Recommend several gravatar avatar caching plug-ins
【Go】Gin源码解读
[go] interpretation of gin source code
让WordPress支持注册用户上传自定义头像功能
【C语言】anonymous/unnamed struct&&union
WordPress database cache plug-in: DB cache Reloaded
统计出现次数最多的前K个字符串
js中Array.prototype.find() 方法在对象数组上无效果,捉急。。。
[issue 30] shopee golang development experience
msf cs openssl流量加密
找到自己的优势,才能干活不累,事半功倍!
Test cos HTML cache static cache plug-in
ELK - X-Pack设置用户密码
在WordPress媒体库中创建文件夹
设置默认收货地址【项目 商城】
17.5 互斥量的概念、用法、死锁演示与解决详解