微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

混合精度算法:大整数尾数的大浮点除法算法?

如何解决混合精度算法:大整数尾数的大浮点除法算法?

我编写了一个运行良好的大整数类。我想写一个大十进制类。我已经将类构建为一个以 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 举报,一经查实,本站将立刻删除。