【js/ts】js/ts高精度加减乘除函数

news2024/9/9 4:45:08

加法

/**
 * 高精度加法函数,处理字符串或数字输入,去除尾部多余的零
 * @param {string|number} a - 被加数
 * @param {string|number} b - 加数
 * @returns {string} - 计算结果,去除尾部多余的零
 * @throws {Error} - 如果输入不是有效的数字,抛出错误
 */
export const add = (a, b) => {
    // 验证输入是否为有效的数字
    const validateNumber = (num) => {
        if (typeof num === 'number' || (typeof num === 'string' && !isNaN(num))) {
            return num.toString();
        } else {
            throw new Error(`Invalid input: ${num}`);
        }
    };
    a = validateNumber(a);
    b = validateNumber(b);
    // 分割整数部分和小数部分
    let [intA = '0', decA = ''] = a.split('.');
    let [intB = '0', decB = ''] = b.split('.');
    // 去除小数部分可能为空的情况
    decA = decA || '0';
    decB = decB || '0';
    // 将小数部分补齐到相同长度
    const maxDecLen = Math.max(decA.length, decB.length);
    decA = decA.padEnd(maxDecLen, '0');
    decB = decB.padEnd(maxDecLen, '0');
    // 转换为整数处理
    const numA = BigInt(intA + decA);
    const numB = BigInt(intB + decB);
    const factor = BigInt('1' + '0'.repeat(maxDecLen));
    // 计算和
    const sum = numA + numB;
    let resultInt = (sum / factor).toString();
    let resultDec = (sum % factor).toString().padStart(maxDecLen, '0');
    // 去除小数部分尾部多余的零
    resultDec = resultDec.replace(/0+$/, '');
    // 拼接结果,处理小数部分
    let result = resultInt;
    if (resultDec.length > 0) {
        result += '.' + resultDec;
    }
    // 如果结果是负零或零,需要转换成0
    if (parseFloat(result) === 0) result = '0';
    return result;
};

减法

/**
 * 高精度减法函数,处理字符串或数字输入,去除尾部多余的零
 * @param {string|number} a - 被减数
 * @param {string|number} b - 减数
 * @returns {string} - 计算结果,去除尾部多余的零
 * @throws {Error} - 如果输入不是有效的数字,抛出错误
 */
export const subtract = (a, b) => {
    // 验证输入是否为有效的数字
    const validateNumber = (num) => {
        if (typeof num === 'number' || (typeof num === 'string' && !isNaN(num))) {
            return num.toString();
        } else {
            throw new Error(`Invalid input: ${num}`);
        }
    };
    a = validateNumber(a);
    b = validateNumber(b);
    // 分割整数部分和小数部分
    let [intA = '0', decA = ''] = a.split('.');
    let [intB = '0', decB = ''] = b.split('.');
    // 去除小数部分可能为空的情况
    decA = decA || '0';
    decB = decB || '0';
    // 将小数部分补齐到相同长度
    const maxDecLen = Math.max(decA.length, decB.length);
    decA = decA.padEnd(maxDecLen, '0');
    decB = decB.padEnd(maxDecLen, '0');
    // 转换为整数处理
    const numA = BigInt(intA + decA);
    const numB = BigInt(intB + decB);
    const factor = BigInt('1' + '0'.repeat(maxDecLen));
    // 计算差
    const diff = numA - numB;
    const isNegative = diff < 0n;
    const absDiff = isNegative ? -diff : diff;
    // 计算整数和小数部分
    let resultInt = (absDiff / factor).toString();
    let resultDec = (absDiff % factor).toString().padStart(maxDecLen, '0');
    // 去除小数部分尾部多余的零
    resultDec = resultDec.replace(/0+$/, '');
    // 拼接结果,处理小数部分
    let result = resultInt;
    if (resultDec.length > 0) {
        result += '.' + resultDec;
    }
    // 添加负号(如果需要)
    if (isNegative) {
        result = '-' + result;
    }
    // 如果结果是负零或零,需要转换成0
    if (parseFloat(result) === 0) result = '0';
    return result;
};

乘法

/**
 * 高精度乘法函数,处理字符串或数字输入,去除尾部多余的零
 * @param {string|number} a - 乘数
 * @param {string|number} b - 被乘数
 * @returns {string} - 计算结果,去除尾部多余的零
 * @throws {Error} - 如果输入不是有效的数字,抛出错误
 */
export const multiply = (a, b) => {
    // 验证输入是否为有效的数字
    const validateNumber = (num) => {
        if (typeof num === 'number' || (typeof num === 'string' && !isNaN(num))) {
            return num.toString();
        } else {
            throw new Error(`Invalid input: ${num}`);
        }
    };
    a = validateNumber(a);
    b = validateNumber(b);
    // 分割整数部分和小数部分
    let [intA = '0', decA = ''] = a.split('.');
    let [intB = '0', decB = ''] = b.split('.');
    // 去除小数部分可能为空的情况
    decA = decA || '0';
    decB = decB || '0';
    // 转换为整数处理
    const numA = BigInt(intA + decA);
    const numB = BigInt(intB + decB);
    // 计算乘积
    const product = numA * numB;
    let result = product.toString();
    // 计算小数位数
    const totalDecLen = decA.length + decB.length;
    // 处理小数部分
    if (totalDecLen > 0) {
        const integerLen = result.length - totalDecLen;
        if (integerLen <= 0) {
            result = '0.' + '0'.repeat(-integerLen) + result;
        } else {
            result = result.slice(0, integerLen) + '.' + result.slice(integerLen);
        }
        result = result.replace(/(\.[0-9]*?)0+$/, '$1').replace(/\.$/, '');
    } else {
        result = result || '0';
    }
    return result;
};

除法

/**
 * 高精度除法函数,处理字符串或数字输入,去除尾部多余的零
 * @param {string|number} dividend - 被除数
 * @param {string|number} divisor - 除数
 * @param {number} precision - 结果保留的小数位数,默认为 28
 * @returns {string} - 计算结果,去除尾部多余的零
 * @throws {Error} - 如果输入不是有效的数字或除数为零,抛出错误
 */
export const highPrecisionDivision = (dividend, divisor, precision = 28) => {
    // 验证输入是否为有效的数字
    const validateNumber = (num) => {
        if (typeof num === 'number' || (typeof num === 'string' && !isNaN(num))) {
            return num.toString();
        } else {
            throw new Error(`Invalid input: ${num}`);
        }
    };
    dividend = validateNumber(dividend);
    divisor = validateNumber(divisor);
    // 将小数点移动到末尾,统一处理
    const moveDecimal = (num) => {
        const [intPart, decPart] = num.split('.');
        return intPart + (decPart || '');
    };
    // 移动小数点
    const movedDividend = moveDecimal(dividend);
    const movedDivisor = moveDecimal(divisor);
    // 转换为 BigInt 处理,保证精度
    const numDividend = BigInt(movedDividend);
    const numDivisor = BigInt(movedDivisor);
    // 计算商和余数
    let quotient = (numDividend / numDivisor).toString();
    // 处理小数部分
    if (precision > 0) {
        const [intPart, decPart = ''] = quotient.split('.');
        let decimalPart = decPart.padEnd(precision, '0');
        decimalPart = decimalPart.slice(0, precision);
        quotient = `${intPart}.${decimalPart}`;
    } else {
        quotient = quotient.split('.')[0]; // 只取整数部分
    }
    // 去除尾部多余的零
    quotient = quotient.replace(/\.?0+$/, '');
    // 如果结果是负零或零,需要转换成0
    if (parseFloat(quotient) === 0) quotient = '0';
    return quotient;
};
add(0.1, "0.3") // 0.4
add(-0.1, "0.3") // 0.2
add(0.1, 0.3) // 0.4
add(0.1687486415614614, 0.3) // 0.4687486415614614
add("5614", "999999999999999991454444444444444444444444444444") // 999999999999999991454444444444444444444444450058


subtract("5", "3") // 2
subtract("-5", "3") // 8
subtract(123.45, "67.89") // 55.56
subtract('561456.514614', "679") // 560777.514614
subtract("1000000000000000000000000000000", "1") // 999999999999999999999999999999


multiply("123", "456") // 56088
multiply("-123", "456") // -56088
multiply(0.52, "67.89") // 35.3028
multiply(0.548568482, "0.5688974989") // 0.3120792373851696698
multiply("1000000000000000000000000000000", "1") // 1000000000000000000000000000000


highPrecisionDivision(10,2) // 5
highPrecisionDivision(-10,2) // -5
highPrecisionDivision(0.456,0.00458) // 0.1249999988609375028980608135
highPrecisionDivision('0.456',0.08) // 0.1249999988609375028980608135
highPrecisionDivision(42424,424732545354332543543) // 0.0000000000000000998840339975

TS封装版本

/**
 * 高精度数学运算函数,处理字符串或数字输入,去除尾部多余的零
 * @param {string|number} a - 第一个操作数
 * @param {string|number} b - 第二个操作数
 * @param {string} operator - 运算符 ('+', '-', '*', '/')
 * @param {number} precision - 除法结果保留的小数位数,默认为 28
 * @returns {string} - 计算结果,去除尾部多余的零
 * @throws {Error} - 如果输入不是有效的数字或除数为零,抛出错误
 */
export const highPrecisionOperation = (a: string | number, b: string | number, operator: string, precision = 28): string => {
    // 验证输入是否为有效的数字
    const validateNumber = (num: string | number): string => {
        if (typeof num === 'number' || (typeof num === 'string' && !isNaN(Number(num)))) {
            return num.toString();
        } else {
            throw new Error(`Invalid input: ${num}`);
        }
    };
    a = validateNumber(a);
    b = validateNumber(b);
    // 分割整数部分和小数部分
    let [intA = '0', decA = ''] = a.split('.');
    let [intB = '0', decB = ''] = b.split('.');
    // 去除小数部分可能为空的情况
    decA = decA || '0';
    decB = decB || '0';
    // 将小数部分补齐到相同长度
    const maxDecLen = Math.max(decA.length, decB.length);
    decA = decA.padEnd(maxDecLen, '0');
    decB = decB.padEnd(maxDecLen, '0');
    // 转换为 BigInt 处理,保证精度
    const numA = BigInt(intA + decA);
    const numB = BigInt(intB + decB);
    const factor = BigInt('1' + '0'.repeat(maxDecLen));
    // 计算结果
    let result: string;
    switch (operator) {
        case '+': {
            const sum = numA + numB;
            let resultInt = (sum / factor).toString();
            let resultDec = (sum % factor).toString().padStart(maxDecLen, '0');
            resultDec = resultDec.replace(/0+$/, ''); // 去除尾部多余的零
            result = resultInt + (resultDec.length > 0 ? '.' + resultDec : '');
            break;
        }
        case '-': {
            const diff = numA - numB;
            const isNegative = diff < 0n;
            const absDiff = isNegative ? -diff : diff;
            let resultInt = (absDiff / factor).toString();
            let resultDec = (absDiff % factor).toString().padStart(maxDecLen, '0');
            resultDec = resultDec.replace(/0+$/, ''); // 去除尾部多余的零
            result = resultInt + (resultDec.length > 0 ? '.' + resultDec : '');
            if (isNegative) {
                result = '-' + result;
            }
            break;
        }
        case '*': {
            const product = numA * numB;
            result = product.toString();
            // 处理小数部分
            if (maxDecLen > 0) {
                const integerLen = result.length - maxDecLen;
                if (integerLen <= 0) {
                    result = '0.' + '0'.repeat(-integerLen) + result;
                } else {
                    result = result.slice(0, integerLen) + '.' + result.slice(integerLen);
                }
                result = result.replace(/(\.[0-9]*?)0+$/, '$1').replace(/\.$/, '');
            } else {
                result = result || '0';
            }
            break;
        }
        case '/': {
            const quotient = (numA / numB).toString();
            const [intPart, decPart = ''] = quotient.split('.');
            let decimalPart = decPart.padEnd(precision, '0');
            decimalPart = decimalPart.slice(0, precision);
            result = `${intPart}.${decimalPart}`;
            result = result.replace(/\.?0+$/, ''); // 去除尾部多余的零
            break;
        }
        default:
            throw new Error(`Unsupported operator: ${operator}`);
    }
    // 如果结果是负零或零,需要转换成 '0'
    if (parseFloat(result) === 0) result = '0';
    return result;
};

使用方法

const resultAdd = highPrecisionOperation('123.456', '789.012', '+');
console.log('加法结果:', resultAdd);

const resultSubtract = highPrecisionOperation('123.456', '789.012', '-');
console.log('减法结果:', resultSubtract);

const resultMultiply = highPrecisionOperation('123.456', '789.012', '*');
console.log('乘法结果:', resultMultiply);

const resultDivision = highPrecisionOperation('123.456', '789.012', '/', 5);
console.log('除法结果:', resultDivision);

在这里插入图片描述
感谢你的阅读,如对你有帮助请收藏+关注!
只分享干货实战精品从不啰嗦!!!
如某处不对请留言评论,欢迎指正~
博主可收徒、常玩QQ飞车,可一起来玩玩鸭~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1918299.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

油罐车的罐体结构介绍

油罐车的罐体一般用优质低碳钢板制成&#xff0c;罐内被隔板分为前、后两部分&#xff0c;相互隔离。每个舱内部均配备一道防波板&#xff0c;以加强罐体的稳定性并减缓行驶中油料对罐体的冲击。其车身由车架、车厢等组成&#xff0c;车架是整个油罐车的骨架&#xff0c;承载着…

项目收获总结--本地缓存方案选型及使用缓存的坑

本地缓存方案选型及使用缓存的坑 一、摘要二、本地缓存三、本地缓存实现方案3.1 自己编程实现一个缓存3.2 基于 Guava Cache 实现本地缓存3.3 基于 Caffeine 实现本地缓存3.4 基于 Encache 实现本地缓存3.5 小结 四、使用缓存的坑4.1 缓存穿透4.2 缓存击穿4.3 缓存雪崩4.4 数据…

浏览器输入URL后的过程

总体流程&#xff1a; 1. 用户输入URL并按下回车 当用户在浏览器的地址栏中输入一个 URL 并按下回车&#xff0c;浏览器开始解析用户输入并判断这是一个合法的 URL。 2. DNS 解析 缓存查找&#xff1a;浏览器首先查看本地 DNS 缓存中是否有对应的 IP&#xff0c;如果有则直接…

分布式系统—存储ceph部署

目录 一、存储概述 1 单机存储设备 2 单机存储的问题 3 商业存储解决方案 4 分布式存储 二、ceph概述 1 ceph优点 2 ceph架构 3 ceph核心组件 4 OSD存储后端 5 ceph数据存储过程 6 ceph版本发行生命周期 7 ceph集群部署 三、基于 ceph-deploy 部署 Ceph 集群 1 …

多位冒充者曝光!全域外卖官方到底是谁?

当前&#xff0c;全域外卖的热度持续攀升&#xff0c;不少创业者在寻找入局途径的同时&#xff0c;也开始打听与全域外卖官方有关的各种信息。其中&#xff0c;以全域外卖官方是谁为代表的身份类信息更是成为了多个创业者群内的热议问题。 而就目前的讨论情况来看&#xff0c;虽…

hyperworks软件许可优化解决方案

Hyperworks软件介绍 Altair 仿真驱动设计改变了产品开发&#xff0c;使工程师能够减少设计迭代和原型测试。提升科学计算能力扩大了应用分析的机会&#xff0c;使大型设计研究能够在限定的项目时间完成。现在&#xff0c;人工智能在工程领域的应用再次改变了产品开发。基于物理…

晋升业内新宠儿,MoE模型给了AI行业两条关键出路

文 | 智能相对论 作者 | 陈泊丞 今年以来&#xff0c;MoE模型成了AI行业的新宠儿。 一方面&#xff0c;越来越多的厂商在自家的闭源模型上采用了MoE架构。在海外&#xff0c;OpenAI的GPT-4、谷歌的Gemini、Mistral AI的Mistral、xAI的Grok-1等主流大模型都采用了MoE架构。 …

回收站清空了怎么恢复回来?8个数据恢复方法汇总分享!

在日常工作中&#xff0c;我们常常会遇到一个令人头痛的问题&#xff1a;回收站清空了怎么恢复回来&#xff1f;这种情况其实比想象中更常见。有时在整理桌面时可能会不小心彻底清理文件&#xff0c;或者误开启了回收站的自动清理功能&#xff0c;甚至可能因为病毒或bug而意外丢…

dxf数据结构

DXF&#xff08;Drawing Exchange Format&#xff0c;绘图交换格式&#xff09;是Autodesk公司开发的一种CAD&#xff08;计算机辅助设计&#xff09;文件格式&#xff0c;用于实现AutoCAD与其他软件之间的CAD数据交换。DXF格式文件是一种开放的矢量数据格式&#xff0c;具有多…

34 超级数据查看器 关联图片

超级数据查看器app&#xff08;excel工具&#xff0c;数据库软件&#xff0c;表格app&#xff09; 关联图片讲解 点击 打开该讲的视频 点击访问app下载页面 豌豆荚 下载地址 大家好&#xff0c;今天我们讲一下超级数据查看器的关联图片功能 这个功能能让表中的每一条信息&…

【区块链 + 智慧政务】城市大脑数据监管平台 | FISCO BCOS应用案例

为了实现城市的智能化管理和服务&#xff0c;智慧城市建设需要将大量的公共数据和社会数据汇集到城市大脑数据中台。 通过汇聚各种类型的数据&#xff0c;城市管理者可以实时了解城市的运行状态和居民的需求&#xff0c;从而更好地进行城市规划、 资源分配和公共服务的提供。 …

Figma中文网?比Figma更懂你的神秘网站!

Figma奠定了在线UI设计工具的基本形式&#xff0c;许多国内设计师都在使用Figma。在本文中&#xff0c;我们将解密国内大型设计师使用的Figma灵魂合作伙伴&#xff0c;被称为Figma中文网络的即时设计资源社区。Figma中文网络UI设计工具的魅力是什么&#xff1f;让我们一起看看吧…

uniapp小程序上传文件webapi后端项目asp.net

需求 小程序需要上传用户相册图片或拍摄的照片到后端服务器 uniapp官方处理小程序文件方法 选择文件方法&#xff1a;uni.chooseMedia uni-app官网uni-app,uniCloud,serverless,uni.chooseVideo(OBJECT),chooseVideo HarmonyOS 兼容性,uni.chooseMedia(OBJECT),uni.saveVid…

EasyExcel批量读取Excel文件数据导入到MySQL表中

1、EasyExcel简介 官网&#xff1a;EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 官网 2、代码实战 首先引入jar包 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</v…

Facebook的未来蓝图:从元宇宙到虚拟现实的跨越

随着科技的不断演进和社会的数字化转型&#xff0c;虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;作为下一代计算平台正逐渐走进人们的视野。作为全球领先的科技公司之一&#xff0c;Facebook正在积极探索并推动这一领域的发展&#xff0c;以实现其…

【linux】服务器卸载cuda

【linux】服务器卸载cuda 文章目录 【linux】服务器卸载cuda1、查找已安装的 CUDA 包&#xff1a;2、卸载 CUDA&#xff1a;3、删除残留文件4、更新系统的包索引&#xff1a;5、检查是否卸载干净&#xff1a; 1、查找已安装的 CUDA 包&#xff1a; dpkg -l | grep cuda2、卸载…

python用selenium网页模拟时无法定位元素解决方法1

进行网页模拟时&#xff0c;有时我们明明可以复制出元素的xpath&#xff0c;但是用selenium的xpath click无法点击到元素。这种情况有几种原因&#xff0c;本文写其中一种——iframe 比如下图网址&#xff0c;第二行出现iframe&#xff0c;则往下的行内元素都会定位不到&#…

07-7.5.1 散列表的基本概念

&#x1f44b; Hi, I’m Beast Cheng &#x1f440; I’m interested in photography, hiking, landscape… &#x1f331; I’m currently learning python, javascript, kotlin… &#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…

并查集+链表,CF 1131F - Asya And Kittens

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1131F - Asya And Kittens 二、解题报告 1、思路分析 本质是拼积木游戏 初始有n块积木&#xff0c;每次两块首尾拼成一块就行&#xff0c;拼接n - 1 次最后会得到一个大积木&#xff0c;我们从左往右输出组…