前端数字计算精度问题

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

举例
// 比如
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 e
  var 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.mfbz.cn/a/581085.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Day20.一刷数据结构算法(C语言版) 669修剪二叉搜索树;108将有序数组转换为二叉搜索树;538把二叉搜索树转换为累加树

一、669修剪二叉搜索树 这道题目比较难&#xff0c;比添加增加和删除节点难的多&#xff0c;建议先看视频理解。 题目链接&#xff1a;修剪二叉搜索树 文章讲解&#xff1a; 代码随想录 视频讲解&#xff1a; 你修剪的方式不对&#xff0c;我来给你纠正一下&#xff01;| 修剪二…

AI预测体彩排列3第2套算法实战化测试第6弹2024年4月28日第6次测试

今天继续进行新算法的测试&#xff0c;今天是第6次测试。好了&#xff0c;废话不多说了&#xff0c;直接上图上结果。 2024年4月28日体彩排3预测结果 6码定位方案如下&#xff1a; 百位&#xff1a;3、2、1、0、5、6、7 十位&#xff1a;3、5、6、2、1、0 个位&#xff1a;3、4…

iOS - 多线程-atomic

文章目录 iOS - 多线程-atomic1. 源码分析1.1 get方法1.2 set方法 2. 一般不使用atomic的原因 iOS - 多线程-atomic atomic用于保证属性setter、getter的原子性操作&#xff0c;相当于在getter和setter内部加了线程同步的锁可以参考源码objc4的objc-accessors.mm它并不能保证使…

【无监督+自然语言】 GPT,BERT, GPT-2,GPT-3 生成式预训练模型方法概述 (Generative Pre-Traning)

主要参考 【GPT&#xff0c;GPT-2&#xff0c;GPT-3 论文精读【李沐论文精读】-2022.03.04】 https://www.bilibili.com/video/BV1AF411b7xQ/ 大语言模型综述&#xff1a; https://blog.csdn.net/imwaters/article/details/137019747 GPT与chatgpt的关系 图源&#xff1a;L…

【Verilog-语法】 条件编译 `ifdef/`ifndef

一、前言 在Verilog项目开发过程中某功能是&#xff0c;一部分代码可能有时候用&#xff0c;有时候不用&#xff0c;为了避免全部编译占用资源&#xff0c;可以使用条件编译语句&#xff1b;尤其在大型项目中还可以节约大量的时间。 二、语法 语法书写格式&#xff1a; &am…

嵌入式Linux学习——Linux常用命令(下)

压缩/解压缩命令 gzip gzip 的常用选项&#xff1a; -l(list) 列出压缩文件的内容。-k(keep) 在压缩或解压时&#xff0c;保留输入文件。-d(decompress) 将压缩文件进行解压缩。 注意&#xff1a; 如果 gzip 不加任何选项&#xff0c;此时为压缩。 压缩完该文件会生成后缀…

web自动化系列-selenium的基本方法介绍

web自动化 &#xff0c;一个老生常谈的话题 &#xff0c;很多人的自动化之路就是从它开始 。它学起来简单 &#xff0c;但做起来又比较难以驾驭 &#xff1b;它的执行效率慢 、但又是最接近于用户的操作场景 &#xff1b; 1.web自动化中的三大亮点技术 我们先聊聊 &#xff0…

hive安装

文章目录 1、下载hive2、安装hadoop&#xff08;略&#xff09;3、安装mysql&#xff08;略&#xff09;4、安装 1、下载hive https://dlcdn.apache.org/hive/hive-3.1.3/ 2、安装hadoop&#xff08;略&#xff09; 3、安装mysql&#xff08;略&#xff09; 4、安装 解压 …

(十一)Servlet教程——Request请求转发

1.Web应用在处理客户端的请求的时候&#xff0c;一般的时候都需要多个资源协同处理&#xff0c;比如先经过一个Servlet的处理&#xff0c;然后再经过另外一个Servlet的处理。但是在一个Servlet中又不能直接调用另外一个Servlet的service方法&#xff0c;所以Servlet就提供了请求…

【嵌入式软件】LWIP 以太网通信

1.互联网模型 1.1 OSI&#xff08;Open System Interconnection&#xff09;七层模型 1&#xff09;应用层&#xff1a; 为上层用户提供应用的接口。常用的应用层的网络协议有&#xff1a;HTTP、FTP、TFTP、SMTP、SNMP、DNS、TELNET、HTTPS、POP3、DHCP 2&#xff09;表示层&…

【C++】C\C++内存管理

下面是围绕C\C内存管理这一块知识谈论相关的内存管理机制&#xff0c;有需要借鉴即可。 同时&#xff0c;我在下面也放了快速建立链表的模板&#xff0c;方便oj题目拿到vs上进行调试。 内存管理目录 1.CPP内存管理1.1new、delete关键字概念1.2特性1.3总结 2.new、delete的底层…

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

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

每日一题:地下城游戏

恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里&#xff0c;他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0…

ThreeJs 环境配置及遇到问题的解决方法

一、环境搭建 ThreeJs在实际在实际使用中更多的是结合框架开发例如&#xff1a;vue框架、react框架&#xff0c;在使用时需要配置开发环境&#xff0c;本文使用的是vscode ThreeJs NodeJs vue 1、ThreeJs安装 下载路径&#xff1a;GitHub - mrdoob/three.js: JavaScript…

CentOS命令大全:掌握关键命令及其精妙用法!

CentOS是一种流行的开源企业级Linux发行版&#xff0c;它基于Red Hat Enterprise Linux (RHEL)的源代码构建。对于系统管理员和运维工程师来说&#xff0c;掌握CentOS的常用命令至关重要。 这些命令不仅可以帮助管理服务器&#xff0c;还可以进行故障排查、性能监控和安全加固等…

【idea】idea 中 git 分支多个提交合并一个提交到新的分支

一、方法原理讲解 我们在 dev 分支对不同的代码文件做了多次提交。现在我们想要把这些提交都合并到 test 分支。首先我们要明白四个 git 操作&#xff0c; commit&#xff1a;命令用于将你的代码变更保存到本地代码仓库中&#xff0c;它创建了一个新的提交&#xff08;commit…

Ubuntu编译安装MariaDB并进行初始化配置

Ubuntu编译安装MariaDB并进行初始化配置 1. 编译安装MariaDB2. 配置MariaDB3. Docker安装MariaDB 1. 编译安装MariaDB MariaDB官方安装文档&#xff1a;https://mariadb.com/kb/en/Build_Environment_Setup_for_Linux/    下载MariaDB源码&#xff1a;https://mariadb.org/ma…

Spring Boot 如何实现缓存预热

Spring Boot 实现缓存预热 1、使用启动监听事件实现缓存预热。2、使用 PostConstruct 注解实现缓存预热。3、使用 CommandLineRunner 或 ApplicationRunner 实现缓存预热。4、通过实现 InitializingBean 接口&#xff0c;并重写 afterPropertiesSet 方法实现缓存预热。 1、使用…

TCP-模拟BS架构通信

简介 bs是通过浏览器进行访问的每次访问都会开启一个短期的socket用来访问服务器的资源 响应报文的格式 服务端 bs架构中的b是浏览器&#xff0c;不需要我们书写&#xff0c;我们只需要书写服务端即可 服务端 public class Server {public static void main(String[] args) {S…

[C++]22:C++11_part_one

C11 一.列表初始化&#xff1a;1.{}初始化&#xff1a;2.C11扩大了列表初始化的范围&#xff1a;3.std::initializer_list1.简单类型的列表初始化&#xff1a;2.复杂类型的列表初始化3.实现vector的列表初始化4.实现list的列表初始化&#xff1a;5.不支持列表初始化&#xff1a…
最新文章