前端数字计算精度问题

news/2024/5/14 9:11:18

计算精度问题通常发生在浮点数运算中,由于浮点数的表示所限,可能导致精度损失。

举例
// 比如
0.1 + 0.2 // 结果为 0.30000000000000004
0.3 - 0.1 // 结果为 0.19999999999999996

vue

vue 使用decimal.js 解决小数相加合计精确度丢失问题

微信小程序

  1. 在utils下创建一个名为commonFunc.js的文件
'use strict';Object.defineProperty(exports, '__esModule', {value: true
});/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
user ,medthor
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 ratio
***************************************************************************** /
/ global Reflect, Promise */function __spreadArrays() {for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;for (var r = Array(s), k = 0, i = 0; i < il; i++)for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)r[k] = a[j];return r;
}
/**
@desc 解决浮动运算问题,避免小数点后产生多位数和计算精度损失。
问题示例:2.3 + 2.4 = 4.699999999999999,1.0 - 0.9 = 0.09999999999999998
**/
/** 
把错误的数据转正
strip(0.09999999999999998)=0.1
*/
function strip(num, precision) {if (precision === void 0) {precision = 15;}return +parseFloat(Number(num).toPrecision(precision));
}
/** 
Return digits length of a number
@param {number} num Input number
*/
function digitLength(num) {// Get digit length of evar eSplit = num.toString().split(/[eE]/);var len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);return len > 0 ? len : 0;
}
/** 
把小数转成整数,支持科学计数法。如果是小数则放大成整数
@param {number} num 输入数
*/
function float2Fixed(num) {if (num.toString().indexOf('e') === -1) {return Number(num.toString().replace('.', ''));}var dLen = digitLength(num);return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
}
/** 
检测数字是否越界,如果越界给出提示
@param {number} num 输入数
*/
function checkBoundary(num) {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");}}
}
/** 
精确乘法
*/
function times(num1, num2) {var others = [];for (var _i = 2; _i < arguments.length; _i++) {others[_i - 2] = arguments[_i];}if (others.length > 0) {return times.apply(void 0, __spreadArrays([times(num1, num2), others[0]], others.slice(1)));}var num1Changed = float2Fixed(num1);var num2Changed = float2Fixed(num2);var baseNum = digitLength(num1) + digitLength(num2);var leftValue = num1Changed * num2Changed;checkBoundary(leftValue);return leftValue / Math.pow(10, baseNum);
}
/** 
精确加法
*/
function plus(num1, num2) {var others = [];for (var _i = 2; _i < arguments.length; _i++) {others[_i - 2] = arguments[_i];}if (others.length > 0) {return plus.apply(void 0, __spreadArrays([plus(num1, num2), others[0]], others.slice(1)));}var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
}
/** 
精确减法
*/
function minus(num1, num2) {var others = [];for (var _i = 2; _i < arguments.length; _i++) {others[_i - 2] = arguments[_i];}if (others.length > 0) {return minus.apply(void 0, __spreadArrays([minus(num1, num2), others[0]], others.slice(1)));}var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
}
/** 
精确除法
*/
function divide(num1, num2) {var others = [];for (var _i = 2; _i < arguments.length; _i++) {others[_i - 2] = arguments[_i];}if (others.length > 0) {return divide.apply(void 0, __spreadArrays([divide(num1, num2), others[0]], others.slice(1)));}var num1Changed = float2Fixed(num1);var num2Changed = float2Fixed(num2);checkBoundary(num1Changed);checkBoundary(num2Changed);// fix: 类似 10 ** -4 为 0.00009999999999999999,strip 修正return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
}
/** 
四舍五入
*/
function round(num, ratio) {var base = Math.pow(10, ratio);return divide(Math.round(times(num, base)), base);
}
var _boundaryCheckingState = true;
/*
是否进行边界检查,默认开启
@param flag 标记开关,true 为开启,false 为关闭,默认为 true
*/
function enableBoundaryChecking(flag) {if (flag === void 0) {flag = true;}_boundaryCheckingState = flag;
}
var index = {strip: strip,plus: plus,minus: minus,times: times,divide: divide,round: round,digitLength: digitLength,float2Fixed: float2Fixed,enableBoundaryChecking: enableBoundaryChecking,
};
exports.strip = strip;
exports.plus = plus;
exports.minus = minus;
exports.times = times;
exports.divide = divide;
exports.round = round;
exports.digitLength = digitLength;
exports.float2Fixed = float2Fixed;
exports.enableBoundaryChecking = enableBoundaryChecking;
exports['default'] = index;
  1. 在页面引用
var commonFunc= require('../../utils/commonFunc');
Page({onload() {commonFunc.minus(0.2, 0.1)}
})

http://www.mrgr.cn/p/22607841

相关文章

双塔模型在召回和粗排的区别

答案参考&#xff1a;推荐系统中&#xff0c;双塔模型用于粗排和用于召回的区别有哪些? - 知乎 召回和粗排在不同阶段面临样本不一样&#xff0c;对双塔来说样本分布差异会使召回和粗排采取不一样的方式。召回打分空间是全部item空间&#xff0c;曝光只有很少一部分&#xff0…

eclipse 如何创建python文件

一、准备 1.平台要求&#xff1a; 电脑除了要安装eclipse软件和Python语言包之外&#xff0c;还需要将Python集成到eclipse软件中&#xff0c;网上有很多的方法&#xff0c;这里就不细细介绍如何集成了。 在下面界面中可以看到自己已经安装了继承插件。具体方法见步骤2&…

Linux网络编程---Socket编程

一、网络套接字 一个文件描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现。) 在通信过程中&#xff0c;套接字一定是成对出现的 套接字通讯原理示意图&#xff1a; 二、预备知识 1. 网络字节序 内存中的多字节数据相对于内存地址有大端和小端之分 小端法&…

【C语言】贪吃蛇详解(附源码)

一、贪吃蛇实现效果 【C语言】贪吃蛇&#xff08;控制台&#xff09; 二、源码 &#x1f388;&#x1f388;&#x1f388;Snake 残风也想永存/C语言项目 - 码云 - 开源中国 (gitee.com)&#x1f388;&#x1f388;&#x1f388; 三、如何使用C语言去实现一个贪吃蛇&#xff1f…

Python数据分析 DataFrame 笔记

08,DataFrame创建 DataFrame是一个【表格型】的数据结构,可以看做是【由Series组成的字典】(共用同一个索引)。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。行索引:index 列索引:columns…

【介绍下分布式系统】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

同事上班这样摸鱼,我坐边上咋看他都在专心写代码啊

我边上有个同事&#xff0c;我坐他边上&#xff0c;但是每天看着他都眉头紧锁&#xff0c;忙的不亦乐乎&#xff0c;但终于有一天&#xff0c;我发现了他上班摸鱼的秘诀。 我劝你千万不要学会这4招&#xff0c;要不就该不好好上班了。 目录 1 上班看电影&#xff1f; 2 上班…

使用joinjs绘制流程图(五)-流程图绘制

效果代码 <template><div class="app"><div ref="myholder" id="paper"></div></div> </template><script> import * as joint from @joint/core export default {data() {return {graph: null,}},mo…

洗地机哪个品牌好?四款性能王者巅峰对决推荐

洗地机的出现&#xff0c;让我们可以高效快速的完成地面清洁&#xff0c;家里干净卫生的同时还让我们有更多的时间去做其他事情。但是面多众多的机型&#xff0c;大家难免有些疑问&#xff0c;究竟哪个好用&#xff0c;怎么挑选到适合我的家用的洗地机&#xff1f;来&#xff0…

云原生Service Mesh服务网格简单介绍

serviceMesh是什么 Service Mesh是一个用于处理服务间通信的基础设施层&#xff0c;旨在实现云原生应用复杂服务拓扑中的可靠请求传递。其基本构成是一组与应用一起部署的轻量级网络代理&#xff0c;这些代理对应用来说是透明的。Service Mesh通过统一的方式来控制和处理服务间…

使用joinjs绘制流程图(二)-Paper对象的属性和方法

效果代码 <template><div class="app"><div ref="myholder" id="paper"></div></div> </template><script> import * as joint from @joint/core export default {data() {return {graph: null,}},mo…

使用joinjs绘制流程图(三)-Rect对象属性

效果代码 <template><div class="app"><div ref="myholder" id="paper"></div></div> </template><script> import * as joint from @joint/core export default {data() {return {graph: null,}},mo…

经典的目标检测算法有哪些?

一、经典的目标检测算法有哪些&#xff1f; 目标检测算法根据其处理流程可以分为两大类&#xff1a;One-Stage&#xff08;单阶段&#xff09;算法和Two-Stage&#xff08;两阶段&#xff09;算法。以下是一些经典的目标检测算法&#xff1a; 单阶段算法: YOLO (You Only Loo…

system -v 信号量的使用

本文介绍了,以图片的形式介绍了system -V IPC信号量的主要作用以及使用的例程,并且用买卖车为例子介绍了信号量的具体使用方法。信号量的作用 信号量是system -v IPC中的一种,通过P、V操作它体现了同步和互斥资源的分配机制。信号量的作用主要可以总结为如下:信号量是syste…

站立会议和燃尽图08

站立会议和燃尽图08 一、小组情况 组长:李宏威 组员:董泽豪 队名:隐约雷名 二、Scrum例会 时间:2024年4月26日 出席人员:李宏威,董泽豪 要求1 工作照片要求2 时间跨度 2024年4月26日 7:00 至 2024年4月26日 7:20 共计 20 分钟 要求3 地点 石家庄铁道大学 要求4 立会内容包…

业财一体化数字化

业财一体化有助于打破业务和财务之间的隔阂,助推企业做好业务洞察,而业财一体化数字化,则可以进一步助推财务业务一体化,提升业务财务的协同效率。这篇文章里,作者就对业财一体化的定义、挑战、以及业财一体化数字化等内容做了拆解,一起来看。 引子 销售人员老王签订了个…

站立会议和燃尽图06

站立会议和燃尽图06 一、小组情况 组长:李宏威 组员:董泽豪 队名:隐约雷名 二、Scrum例会 时间:2024年4月24日 出席人员:李宏威,董泽豪 要求1 工作照片要求2 时间跨度 2024年4月24日 7:00 至 2024年4月24日 7:20 共计 20 分钟 要求3 地点 石家庄铁道大学 要求4 立会内容包…

站立会议和燃尽图07

站立会议和燃尽图07 一、小组情况 组长:李宏威 组员:董泽豪 队名:隐约雷名 二、Scrum例会 时间:2024年4月25日 出席人员:李宏威,董泽豪 要求1 工作照片要求2 时间跨度 2024年4月25日 7:00 至 2024年4月25日 7:20 共计 20 分钟 要求3 地点 石家庄铁道大学 要求4 立会内容包…

智慧供热一站式热网平衡多功能集成系统

供热管理地域分散的现实&#xff0c;决定必须采用先进技术手段开发软件系统&#xff0c;使各管理单位互联互通。在多年技术积累的基础上&#xff0c;公司采用目前成熟而且领先的技术架构&#xff0c;研发了适用于多个组织机构集中式管理的供热管理软件。使管理在技术上不再受地…

基于stm32的USB模拟UART的实现

目录 基于stm32的USB模拟UART的实现实验目的场景使用原理图USBX 组件移植USBX实现虚拟串口配置USB移植USBX源码工程中添加对应源码修改usb.c创建 USBX 任务添加使用串口的代码上机现象本文中使用的测试工程 基于stm32的USB模拟UART的实现 本文目标&#xff1a;基于stm32的USB模…