问题描述
我编写了一个运行良好的大整数类。我想写一个大十进制类。我已经将类构建为一个以 10 为底的指数的浮点数——即以 M*10^e 的形式,其中 10^0 表示数字位于 [0.1,1 之间)。
这里,M 是一个 BigInteger,10^e 用于确定小数点在哪里。我想除以这些数字。当商大于1时,我可以做整数除法来确定小数点应该在哪里。当分子大小大于分母时,整数相除的结果小于一。我怎么知道小数点在哪里?
请注意,为了在不损失精度的情况下执行除法,我在除法之前将分子乘以 10 的大幂,例如 10^24。
我试过对指数求差(例如 10^(e1 - e2))。大多数情况下这会产生正确的答案,但有时指数会偏离 1。当分子大于分母时也会发生这种情况。
为了说明问题: 7210^2 / 3510^2 = ~2.06 但是对指数求差会给我 ~0.206。
注意:我知道以 2 为底的指数项会更好,而我的 BigInteger 类使用以 2 为底的数字,但我也不知道如何确定小数应该与以 2 为基数的位置。此外,该类是用 AssemblyScript 编写的,它的语法类似于 TypeScript,后者类似于 JavaScript。我不能使用外部包。
完全实现:https://github.com/Web3-API/as-bigint/blob/main/assembly/BigFloat.ts
除法功能:
div(other: BigFloat,minPrecision: i32 = this.minPrecision): BigFloat {
let dividend = this.mantissa;
let divisor = other.mantissa;
// divide with padding to maintain precision
let dividendLength = dividend.toString().length - (dividend.isNegative ? 1 : 0);
let divisorLength = divisor.toString().length - (divisor.isNegative ? 1 : 0);
const lengthDiff = dividendLength - divisorLength;
const padding = minPrecision - (lengthDiff < 0 ? lengthDiff : 0);
dividend = BigFloat.mulBigIntPowTen(dividend,padding);
const mantissa: BigInt = dividend.div(divisor);
// calculate exponent
let exponent: i32;
const gteZero: boolean = this.mantissa.magCompareto(other.mantissa) >= 0;
if (gteZero) {
const naiveDiv: BigInt = this.mantissa.div(other.mantissa);
const naiveDivLen: i32 = naiveDiv.toString().length;
exponent = naiveDiv.isNegative ? naiveDivLen - 1 : naiveDivLen;
} else {
exponent = this.e - other.e;
}
return new BigFloat(mantissa,exponent,this.minPrecision);
}
测试用例(查看“从分数构造”部分):https://github.com/Web3-API/as-bigint/blob/main/assembly/__tests__/BigFloat_read_write.spec.ts
此测试用例由于小数点位置的差一错误而失败:
numerator = BigInt.fromString("23627");
denominator = BigInt.fromString("1093746923469083704986");
bigFloat = BigFloat.fromFraction(numerator,denominator,30);
expect(bigFloat.toString(30)).toStrictEqual("0.000000000000000021601889333833");
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)