提问人:Kris B. 提问时间:4/24/2021 最后编辑:Kris B. 更新时间:4/25/2021 访问量:201
混合精度算术:大整数尾数的大浮点除法算法?
Mixed precision arithmetic: Algorithm for big float division with big integer mantissa?
问:
我写了一个运行良好的 Big Integer 类。我想写一个大十进制类。我将类构建为以 10 为基数指数的浮点数,即以 M*10^e 的形式,其中 10^0 表示数字介于 [0.1, 1] 之间。
这里,M 是一个 BigInteger,10^e 用于确定小数点的位置。我想把这些数字除以。当商大于 1 时,我可以进行整数除法以确定小数点应该在哪里。当分子的大小大于分母时,整数除法的结果小于 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");
答: 暂无答案
评论
M