问题描述
我一直在使用BigNumber.js库进行高精度算术计算。为了保持更高的精度,我正在使用Bignumber对象的toFixed
方法,如下所示:
(new BigNumber(6000 )).minus(9006000).div(9006000).times(4503000 ).plus(4503000 ).toFixed()
上面的代码给出的结果为2999.99999999999998275
。我尝试使用decimal
数据类型在C#中验证此计算结果,因为十进制的精度高于双精度,但结果在粒度级别上有所不同。
decimal rg1 = 6000m;
decimal lastSavedRG1 = 9006000m;
decimal lastsavedrefinedgoalMonthly1 = 4503000m;
decimal cal1 = (lastsavedrefinedgoalMonthly1 + (lastsavedrefinedgoalMonthly1 * ((rg1 - lastSavedRG1) / lastSavedRG1)));
此计算得出的值为3000.0000000000000000000001
。知道为什么会有这样的差异吗?
解决方法
为了澄清我的意见-JS中的BigNumber
是任意精度的数字。这意味着它可以存储任意大小的数字。但是,小数部分不能具有任意精度,因为许多数字具有无限的十进制扩展。像1 / 3
或sqrt(2)
这样的简单表达式的小数部分具有无限数量的数字。为此,bigjs中有一个配置选项-DECIMAL_PLACES
定义为:
另一方面,运算结果的最大小数位数 涉及除法,即除法,平方根和基数转换 运算和具有负指数的幂运算。
C#十进制不是任意精度类型。它具有28-29位数字的固定大小和固定精度(如文档中所述)。该数字包括点之前和之后的数字。
这意味着,如果将DECIMAL_PLACES
设置为28,然后将两个数字除以小于1的结果-该结果应与C#十进制一致。但是,只要将结果乘以更大的数字,它们就会开始产生分歧。 BigJS在点后仍将有28位数字,但是C#十进制总共有28位数字,因此,例如,如果结果为10000,则小数部分的精确数字位数为28-5 = 23,它们将开始为不同意。
简而言之-您需要找到C#的第三方库,该库提供相同的分数任意精度数字(BigInteger
不够,因为它是整数)。