代码之家  ›  专栏  ›  技术社区  ›  Node.JS

尝试理解BigInteger的sage数字系统

  •  3
  • Node.JS  · 技术社区  · 10 年前

    我有以下内容 sage 我正在尝试将它转换为Java(使用Java的内置BigInteger库)。但我并不成功。

    简而言之,我初始化了 N 作为一个 BigInteger 希腊字母表的第4个字母 作为double,为了计算幂(BigInteger^double),我转换了 N 到BigDecimal(即。 new BigDecimal(BigInteger)) 然后:

    1. 我用过 this 但速度太慢(非常慢)。
    2. 我用过 this 但我失去了太多的精确度。
    3. 我用过 this 但我得到溢出异常。

    N = 16260595201356777876687102055392856230368799478725437225418970788404092751540966827614883675066492383688147288741223234174448378892794567789551235835087027626536919406320142455677084743499141155821894102610573207343199194327005172833989486958434982393556326206485954223151805798621294965926069728816780985683043030371485847746616146554612001066554175545753760388987584593091716701780398711910886679925612838955858736102229719042291682456480437908426849734556856917891628730543729446245974891735371991588505429152639045721840213451875487038496578525189542369448895368117152818687795094021869963915318643663536132393791
    delta = 0.26
    X = 2*floor(N^delta) # in sage, ^ operator means exponentiation
                         # similar to ** operator in python
    
    print("X:" + str(x))
    

    输出:

    十: 3280389927029707062119372107312345964260111899897304812053673705723402525308231239351958928382082199676426399488721710159859316222019683979411877007525412864


    魔法是什么?圣人是怎么做到的?如何将此代码转换为Java(并能够得到类似的结果),应该有一些解决方案。

    1 回复  |  直到 9 年前
        1
  •  2
  •   Roman    10 年前

    您可以使用方法#1来解决问题。问题是 BigFunctions.ln() 对于整数部分较大的数字(小数点左侧的位数)不是很有效。作为一种解决方法,我对数字进行了缩放,使其在整数部分最多包含一个数字,然后通过添加进行补偿 ln(10) * rescale * delta 对…的论点 exp() .
    您还应该注意,使用 new BigDecimal(double) 构造函数导致精度损失-读取 javadoc 以进行解释。相反,您应该使用 new BigDecimal(String) (特别是如果该双精度值来自某种配置值),或 BigDecimal.valueOf(double) .

    BigInteger N = new BigInteger("16260595201356777876687102055392856230368799478725437225418970788404092751540966827614883675066492383688147288741223234174448378892794567789551235835087027626536919406320142455677084743499141155821894102610573207343199194327005172833989486958434982393556326206485954223151805798621294965926069728816780985683043030371485847746616146554612001066554175545753760388987584593091716701780398711910886679925612838955858736102229719042291682456480437908426849734556856917891628730543729446245974891735371991588505429152639045721840213451875487038496578525189542369448895368117152818687795094021869963915318643663536132393791");
    double delta = 0.26;
    
    // this scale is sufficient to get the exact integer part
    // it is roughly equal to the number of digits in the result's integer part
    final int SCALE = 170;
    BigDecimal x = new BigDecimal(N);
    BigDecimal y = BigDecimal.valueOf(delta);
    
    int maxIntDigits = 1;
    int intDigits = x.precision() - x.scale();
    int rescale = Math.max(intDigits - maxIntDigits, 0);
    BigDecimal rescaledX = x.scaleByPowerOfTen(-rescale);
    
    BigDecimal z = BigFunctions.exp(
            BigFunctions.ln(rescaledX, SCALE)
                    .add(BigFunctions.ln(BigDecimal.TEN, SCALE).multiply(BigDecimal.valueOf(rescale)))
                    .multiply(y),
            SCALE)
            .setScale(0, BigDecimal.ROUND_FLOOR)
            .multiply(BigDecimal.valueOf(2));
    
    System.out.println(z);
    

    输出:

    32803899270296656086551107648280231830313861082788744611797945239672375099902513857958219091523648839375388564236289659519690404775361188478777234501437677352644