目录

java大数运算详解【其一】大数加减法

java大数运算详解【其二】大数乘法

java大数运算详解【其三】大数乘法之平方算法之按位二次展开式算法

java大数运算详解【其四】大数乘法之平方算法之Karatsuba平方算法

java大数运算详解【其五】大数乘法之平方算法之ToomCook3平方算法

java大数运算详解【其六】大数乘法之单位乘法和经典乘法

java大数运算详解【其七】大数乘法之Karatsuba乘法和ToomCook3乘法

java大数运算详解【其八】大数除法

java大数运算详解【其九】大数除法之试商法(Knuth除法)核心算法

java大数运算详解【其十】大数除法之Burnikel-Ziegler除法算法

所有解释都是最基本的,没有过多赘述,如若不懂静心思考。
    1.1、按位二次展开式算法
    /**
     * 将整型数组x的内容平方,结果放入整型数组z中,x的内容不变。
     */
    private static final int[] squareToLen(int[] x, int len, int[] z) {
         int zlen = len << 1;
         if (z == null || z.length < zlen)
             z = new int[zlen];
         // 在调用intrinsified(增强)方法之前执行检查。
         implSquareToLenChecks(x, len, z, zlen);
         return implSquareToLen(x, len, z, zlen);
     }
     /**
      * 参数验证。
      */
     private static void implSquareToLenChecks(int[] x, int len, int[] z, int zlen) throws RuntimeException {
         if (len < 1) {
             throw new IllegalArgumentException("invalid input length: " + len);
         }
         if (len > x.length) {
             throw new IllegalArgumentException("input length out of bound: " +
                                        len + " > " + x.length);
         }
         if (len * 2 > z.length) {
             throw new IllegalArgumentException("input length out of bound: " +
                                        (len * 2) + " > " + z.length);
         }
         if (zlen < 1) {
             throw new IllegalArgumentException("invalid input length: " + zlen);
         }
         if (zlen > z.length) {
             throw new IllegalArgumentException("input length out of bound: " +
                                        len + " > " + z.length);
         }
     }
     /**
      * Java运行时可以为该方法使用intrinsic(固有的,增强的)。
      */
     @HotSpotIntrinsicCandidate
     private static final int[] implSquareToLen(int[] x, int len, int[] z, int zlen) {
        /*
         * 这里使用的算法来自Colin Plumb的C库。
         * 技巧:考虑乘法中的部分乘积
         * “abcde”本身:
         *
         *               a  b  c  d  e
         *            *  a  b  c  d  e
         *          ==================
         *              ae be ce de ee
         *           ad bd cd dd de
         *        ac bc cc cd ce
         *     ab bb bc bd be
         *  aa ab ac ad ae
         *
         * 注意主对角线以上的所有元素:
         *              ae be ce de = (abcd) * e
         *           ad bd cd       = (abc) * d
         *        ac bc             = (ab) * c
         *     ab                   = (a) * b
         *
         * 是主对角线以下所有内容的副本:
         *                       de
         *                 cd ce
         *           bc bd be
         *     ab ac ad ae
         *
         * 因此,总和是2 *(对角线上方或下方)+对角线。
         *
         * 这是从对角线开始累积的(对角线由输入数字的平方组成),
         * 然后对角线除以2,非对角线相加,再乘以2。
         * 低位只是输入低位的一个副本,因此不需要特别注意。
         */
        // 储存平方值,右移一位(即,除以2)。
        int lastProductLowWord = 0;
        for (int j=0, i=0; j < len; j++) {//计算每一位的平方值并存储在z中且右移一位
            long piece = (x[j] & LONG_MASK);
            long product = piece * piece;
            z[i++] = (lastProductLowWord << 31) | (int)(product >>> 33);
            z[i++] = (int)(product >>> 1);
            lastProductLowWord = (int)product;
        }
        // 计算对角线上方或下方的总和
        for (int i=len, offset=1; i > 0; i--, offset+=2) {//注意:offset-1=2*(len-i),即:2*len-offset=2*i-1.
            int t = x[i-1];
            t = mulAdd(z, x, offset, i-1, t);
            addOne(z, offset-1, i, t);//t的添加位置为z[z.length-1-(offset-1)-i],即:z[2*len-offset-i].
            //故addOne函数最多需进位传播2*len-offset-i=i-1次,为判断运算是否溢出,需传参mlen为i,而不是i-1.
            //其实运算一定不会产生溢出(zlen=2*len时),所以传参mlen为i-1也可行(同时传参offset为offset)。
        }
        // 回移并设置低位
        primitiveLeftShift(z, zlen, 1);
        z[zlen-1] |= x[len-1] & 1;
        return z;
    }
    /**
     * 将数组乘以一个整数k,然后添加到结果中,返回进位。
     */
    static int mulAdd(int[] out, int[] in, int offset, int len, int k) {
        implMulAddCheck(out, in, offset, len, k);
        return implMulAdd(out, in, offset, len, k);
    }
    /**
     * 参数验证。
     */
    private static void implMulAddCheck(int[] out, int[] in, int offset, int len, int k) {
        if (len > in.length) {
            throw new IllegalArgumentException("input length is out of bound: " + len + " > " + in.length);
        }
        if (offset < 0) {
            throw new IllegalArgumentException("input offset is invalid: " + offset);
        }
        if (offset > (out.length - 1)) {
            throw new IllegalArgumentException("input offset is out of bound: " + offset + " > " + (out.length - 1));
        }
        if (len > (out.length - offset)) {
            throw new IllegalArgumentException("input len is out of bound: " + len + " > " + (out.length - offset));
        }
    }
    /**
     * Java运行时可以为该方法使用intrinsic(固有的,增强的)。
     * 将in数组(长度为len,数据倒序存储)乘以k,再添加到out数组(偏移量为offset,数据倒序存储),
     * 添加位置为第offset位,即out[out.length-offset - 1].
     * 返回进位。
     */
    @HotSpotIntrinsicCandidate
    private static int implMulAdd(int[] out, int[] in, int offset, int len, int k) {
        long kLong = k & LONG_MASK;
        long carry = 0;
        offset = out.length-offset - 1;//重计算偏移量
        for (int j=len-1; j >= 0; j--) {
            long product = (in[j] & LONG_MASK) * kLong +
                           (out[offset] & LONG_MASK) + carry;
            out[offset--] = (int)product;
            carry = product >>> 32;
        }
        return (int)carry;
    }
    /**
     * 在a中加上一个整数,把carry这个整数加到a中。
     * 把carry添加到a中,添加位置为第offset+mlen位,即a[a.length-1-mlen-offset].
     * 进位最多传播mlen位。
     * 返回结果进位。
     */
    static int addOne(int[] a, int offset, int mlen, int carry) {
        offset = a.length-1-mlen-offset;
        long t = (a[offset] & LONG_MASK) + (carry & LONG_MASK);
        a[offset] = (int)t;
        if ((t >>> 32) == 0)
            return 0;
        while (--mlen >= 0) {
            if (--offset < 0) { // 数据溢出
                return 1;
            } else {
                a[offset]++;
                if (a[offset] != 0)
                    return 0;//进位传播处理完成,返回0
            }
        }
        return 1;//进位传播了mlen次,仍未处理完毕,返回进位1
    }
    // 将a数组(长度len,数据倒序存储)左移n位,假设没有前导零,0<=n<32.
    static void primitiveLeftShift(int[] a, int len, int n) {
        if (len == 0 || n == 0)
            return;
        int n2 = 32 - n;
        for (int i=0, c=a[i], m=i+len-1; i < m; i++) {//循环移位
            int b = c;
            c = a[i+1];
            a[i] = (b << n) | (c >>> n2);
        }
        a[len-1] <<= n;
    }
    按位二次展开式算法,即将mag数组看作len个项的和,并使用二次展开式进行计算其平方值。

java大数运算详解【其三】大数乘法之平方算法之按位二次展开式算法相关推荐

  1. java三元运算详解

    运算符 2.1 运算符概念 运算符是用来计算数据的指令.数据可以是常量,也可以是变量.被运算符操作的数成为操作数. Int x = 3; Int y = 4; Int z = x + y 2.2 算数 ...

  2. 大数取余运算(详解)

    大数取余运算(详解) //(19^3 mod 23)^2 mod 31=25 //a=19 b=3 c=23 d=2 e=31 #include<stdio.h> long long po ...

  3. 一篇搞定位运算——java位运算详解

    java位运算详解 前言 一.位运算符 &:按位与 |:按位或 ~:按位非 ^:按位异或 <<:左位移运算符 >>:右位移运算符 <<<:无符号右移运 ...

  4. java拉姆达表达式事例,Java Lambda表达式详解和实例

    简介 Lambda表达式是Java SE 8中一个重要的新特性.lambda表达式允许你通过表达式来代替功能接口. lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体( ...

  5. 5W字高质量java并发系列详解教程(上)-附PDF下载

    文章目录 第一章 java.util.concurrent简介 主要的组件 Executor ExecutorService ScheduledExecutorService Future Count ...

  6. Java 线程池详解及实例代码

    转载自  Java 线程池详解及实例代码 这篇文章主要介绍了Java 线程池的相关资料,并符实例代码,帮助大家学习参考,需要的朋友可以参考下 线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时 ...

  7. python开方运算符_Pytorch Tensor基本数学运算详解

    1. 加法运算 示例代码: import torch # 这两个Tensor加减乘除会对b自动进行Broadcasting a = torch.rand(3, 4) b = torch.rand(4) ...

  8. 取模(余)%运算详解

    取模(余)%运算详解 1.JAVA中 对于整型数a,b来说,取模运算是:               1.求 整数商: c = a/b;               2.计算模: a%b = a - ...

  9. Java 三目运算符细节详解

    Java 三目运算符细节详解 @author:Jingdai @date:2020.09.24 看到标题你肯定觉得三目运算符有什么好讲的,不是很简单嘛.我之前也是这么认为的,直到今天刷LeetCode ...

最新文章

  1. ZJU-java进阶笔记 第四周(继承与多态)
  2. Laravel 框架安装
  3. snmpset对象不可写_[Python]可变对象与多进程通信
  4. luogu P2257 YY的GCD
  5. java两个数之间质数求法,求任意两个整数之间质数的个数的代码!!!(新手编写)...
  6. HDOJ 4005-The war解题报告
  7. 五一假期四天_假期在家上班的12天
  8. [HNOI2015]开店
  9. 完美的xslt数值函数与字符串函数
  10. dev gridcontrol 单选框效果
  11. python 打包过程
  12. 9.STC15W408AS单片机EEPROM
  13. 计量芯片应用心得之软件篇
  14. 2019NEFU寒假集训新生考试 2020.1.6
  15. 照片调色系列教程(11):浪漫色调 温情暖暖
  16. Nginx反向代理服务器及负载均衡服务配置实战
  17. List.isEmpty()与CollectionUtils.isEmpty的区别
  18. Android各个版本的区别
  19. 计算机二级MS-office题目练习
  20. 谷歌Pixel 4神奇在哪儿? AI黑科技带来四大改变!

热门文章

  1. [yii]Trying to get property of non-object
  2. Gartner数据库推荐报告,巨杉数据库入选
  3. VDP6.1.3部署使用
  4. 思科华为路由器如何利用route-map配置双wan口策略路由
  5. C++调用Matlab混合编程未定义函数或变量“javaaddpath“
  6. C++11 std::tuple
  7. 【Graphics·二】带反射和折射的Fresnel函数
  8. 数列的逆序数对(难度系数:2颗星)
  9. 求数组中数对之差的最大值
  10. 测量两种充电9V电池