C#,《小白学程序》第二十六课:大数乘法(BigInteger Multiply)的Toom-Cook 3算法及源程序

凑数的,仅供参考。

1 文本格式

/// <summary>
/// 《小白学程序》第二十六课:大数(BigInteger)的Toom-Cook 3乘法
/// Toom-Cook 3-Way Multiplication
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static string toom_cook3_multiply(string a, string b)
{
    int n = Math.Max(a.Length, b.Length);
    int[] ra = string_to_digitals(a, n);
    int[] rb = string_to_digitals(b, n);
    toom_cook3_process_00(ra, rb, out int[] rz);
    toom_cook3_carry(rz, n * 2);
    return digitals_to_string(rz);
}

/// <summary>
/// 短数字的乘法(常规乘法,小学生算法)
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="z"></param>
private static void toom_cook3_normal(int[] a, int[] b, ref int[] z)
{
    int n = a.Length;
    for (int j = 0; j < n; j++)
    {
        for (int i = 0; i < n; i++)
        {
            z[j + i] += a[i] * b[j];
        }
    }
}

/// <summary>
/// 完全按原始C++代码改写;运行成功;
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="z"></param>
private static void toom_cook3_process_01(int[] a, int[] b, out int[] z)
{
    int n = a.Length;
    int n1 = n * 1 / 3;
    int n2 = n * 2 / 3;
    int n3 = n * 3 / 3;
    int n4 = n * 4 / 3;

    z = new int[n * 2];
    if (n <= 9)
    {
        toom_cook3_normal(a, b, ref z);
        return;
    }

    // int *a0 = &a[0];
    // Multiplicand / right side array pointer
    int a0 = 0;
    // int *a1 = &a[tLen / 3];
    // Multiplicand / central array pointer
    int a1 = n1;
    // int *a2 = &a[tLen * 2/ 3];
    // Multiplicand / left side array pointer
    int a2 = n2;// n * 2 / 3;

    // int *b0 = &b[0];
    // Multiplier / right side array pointer
    int b0 = 0;
    // int *b1 = &b[tLen / 3];
    // Multiplier / central array pointer
    int b1 = n1;
    // int *b2 = &b[tLen * 2 / 3];
    // Multiplier / left side array pointer
    int b2 = n2;// n * 2 / 3;

    // int *c0 = &z[(tLen / 3) * 0];
    int[] c0 = new int[n2];
    int[] c1 = new int[n2];
    // int *c2 = &z[(tLen / 3) * 2];
    int[] c2 = new int[n2];
    int[] c3 = new int[n2];
    // int *c4 = &z[(tLen / 3) * 4];
    int[] c4 = new int[n2];

    int[] a_m2 = new int[n1];  // a(-2)
    int[] a_m1 = new int[n1];  // a(-1)
    int[] a_0 = new int[n1];   // a(0)
    int[] a_1 = new int[n1];   // a(1)
    int[] a_inf = new int[n1]; // a(inf)
    int[] b_m2 = new int[n1];  // b-2)
    int[] b_m1 = new int[n1];  // b-1)
    int[] b_0 = new int[n1];   // b(0)
    int[] b_1 = new int[n1];   // b(1)
    int[] b_inf = new int[n1]; // b(inf)

    // ==== a(-2) = 4 * a2 - 2 * a1 + a0, b(-2) = 4 * b2 - 2 * b1 + b0
    for (int i = 0; i < n1; i++)
    {
        a_m2[i] = (a[a2 + i] << 2) - (a[a1 + i] << 1) + a[a0 + i];
        b_m2[i] = (b[b2 + i] << 2) - (b[b1 + i] << 1) + b[b0 + i];
    }
    // ==== c(-2) = a(-2) * b(-2)
    toom_cook3_process_01(a_m2, b_m2, out int[] c_m2);

    // ==== a(-1) = a2 - a1 + a0, b(-1) = b2 - b1 + b0
    for (int i = 0; i < n1; i++)
    {
        a_m1[i] = a[a2 + i] - a[a1 + i] + a[a0 + i];
        b_m1[i] = b[b2 + i] - b[b1 + i] + b[b0 + i];
    }
    // ==== c(-1) = a(-1) * b(-1)
    toom_cook3_process_01(a_m1, b_m1, out int[] c_m1);

    // ==== a(0) = a0, b(0) = b0
    for (int i = 0; i < n1; i++)
    {
        a_0[i] = a[a0 + i];
        b_0[i] = b[b0 + i];
    }
    // ==== c(0) = a(0) * b(0)
    toom_cook3_process_01(a_0, b_0, out int[] c_0);

    // ==== a(1) = a2 + a1 + a0, b(1) = b2 + b1 + b0
    for (int i = 0; i < n1; i++)
    {
        a_1[i] = a[a2 + i] + a[a1 + i] + a[a0 + i];
        b_1[i] = b[b2 + i] + b[b1 + i] + b[b0 + i];
    }
    // ==== c(1) = a(1) * b(1)
    toom_cook3_process_01(a_1, b_1, out int[] c_1);

    // ==== a(inf) = a2, b(inf) = b2
    for (int i = 0; i < n1; i++)
    {
        a_inf[i] = a[a2 + i];
        b_inf[i] = b[b2 + i];
    }

    // ==== c(inf) = a(inf) * b(inf)
    toom_cook3_process_01(a_inf, b_inf, out int[] c_inf);

    // ==== c4 = 6 * c(inf) / 6
    for (int i = 0; i < n2; i++)
    {
        c4[i] = c_inf[i];
    }
    // ==== c3 = -c(-2) + 3 * c(-1) - 3 * c(0) + c(1) + 12 * c(inf) / 6
    for (int i = 0; i < n2; i++)
    {
        c3[i] = -c_m2[i];
        c3[i] += (c_m1[i] << 1) + c_m1[i];
        c3[i] -= (c_0[i] << 1) + c_0[i];
        c3[i] += c_1[i];
        c3[i] += (c_inf[i] << 3) + (c_inf[i] << 2);
        c3[i] /= 6;
    }
    // ==== c2 = 3 * c(-1) - 6 * c(0) + 3 * c(1) - 6 * c(inf) / 6
    for (int i = 0; i < n2; i++)
    {
        c2[i] = (c_m1[i] << 1) + c_m1[i];
        c2[i] -= (c_0[i] << 2) + (c_0[i] << 1);
        c2[i] += (c_1[i] << 1) + c_1[i];
        c2[i] -= (c_inf[i] << 2) + (c_inf[i] << 1);
        c2[i] /= 6;
    }
    // ==== c1 = c(-2) - 6 * c(-1) + 3 * c(0) + 2 * c(1) - 12 * c(inf) / 6
    for (int i = 0; i < n2; i++)
    {
        c1[i] = c_m2[i];
        c1[i] -= (c_m1[i] << 2) + (c_m1[i] << 1);
        c1[i] += (c_0[i] << 1) + c_0[i];
        c1[i] += (c_1[i] << 1);
        c1[i] -= (c_inf[i] << 3) + (c_inf[i] << 2);
        c1[i] /= 6;
    }
    // ==== c0 = 6 * c(0) / 6
    for (int i = 0; i < n2; i++)
    {
        c0[i] = c_0[i];
    }
    // ==== z = c4 * x^4 + c3 * x^3 + c2 * x^2 + c1 * x + c0
    for (int i = 0; i < n2; i++)
    {
        z[i + n4] += c4[i];
        z[i + n3] += c3[i];
        z[i + n2] += c2[i];
        z[i + n1] += c1[i];
        z[i] += c0[i];
    }
}
 


    /// <summary>
    /// 乘积和的进位计算
    /// </summary>
    /// <param name="a"></param>
    /// <param name="n"></param>
    /// <exception cref="Exception"></exception>
    private static void toom_cook3_carry(int[] a, int n)
    {
        int cr = 0;
        for (int i = 0; i < n; i++)
        {
            a[i] += cr;
            if (a[i] < 0)
            {
                cr = -(-(a[i] + 1) / 10 + 1);
            }
            else
            {
                cr = a[i] / 10;
            }
            a[i] -= cr * 10;
        }
        if (cr != 0)
        {
            // Overflow
            throw new Exception("OVERFLOW! cr=" + cr);
        }
    }

2 代码格式

/// <summary>
/// 《小白学程序》第二十六课:大数(BigInteger)的Toom-Cook 3乘法
/// Toom-Cook 3-Way Multiplication
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static string toom_cook3_multiply(string a, string b)
{int n = Math.Max(a.Length, b.Length);int[] ra = string_to_digitals(a, n);int[] rb = string_to_digitals(b, n);toom_cook3_process_00(ra, rb, out int[] rz);toom_cook3_carry(rz, n * 2);return digitals_to_string(rz);
}/// <summary>
/// 短数字的乘法(常规乘法,小学生算法)
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="z"></param>
private static void toom_cook3_normal(int[] a, int[] b, ref int[] z)
{int n = a.Length;for (int j = 0; j < n; j++){for (int i = 0; i < n; i++){z[j + i] += a[i] * b[j];}}
}/// <summary>
/// 完全按原始C++代码改写;运行成功;
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="z"></param>
private static void toom_cook3_process_01(int[] a, int[] b, out int[] z)
{int n = a.Length;int n1 = n * 1 / 3;int n2 = n * 2 / 3;int n3 = n * 3 / 3;int n4 = n * 4 / 3;z = new int[n * 2];if (n <= 9){toom_cook3_normal(a, b, ref z);return;}// int *a0 = &a[0];// Multiplicand / right side array pointerint a0 = 0;// int *a1 = &a[tLen / 3];// Multiplicand / central array pointerint a1 = n1;// int *a2 = &a[tLen * 2/ 3];// Multiplicand / left side array pointerint a2 = n2;// n * 2 / 3;// int *b0 = &b[0];// Multiplier / right side array pointerint b0 = 0;// int *b1 = &b[tLen / 3];// Multiplier / central array pointerint b1 = n1;// int *b2 = &b[tLen * 2 / 3];// Multiplier / left side array pointerint b2 = n2;// n * 2 / 3;// int *c0 = &z[(tLen / 3) * 0];int[] c0 = new int[n2];int[] c1 = new int[n2];// int *c2 = &z[(tLen / 3) * 2];int[] c2 = new int[n2];int[] c3 = new int[n2];// int *c4 = &z[(tLen / 3) * 4];int[] c4 = new int[n2];int[] a_m2 = new int[n1];  // a(-2)int[] a_m1 = new int[n1];  // a(-1)int[] a_0 = new int[n1];   // a(0)int[] a_1 = new int[n1];   // a(1)int[] a_inf = new int[n1]; // a(inf)int[] b_m2 = new int[n1];  // b-2)int[] b_m1 = new int[n1];  // b-1)int[] b_0 = new int[n1];   // b(0)int[] b_1 = new int[n1];   // b(1)int[] b_inf = new int[n1]; // b(inf)// ==== a(-2) = 4 * a2 - 2 * a1 + a0, b(-2) = 4 * b2 - 2 * b1 + b0for (int i = 0; i < n1; i++){a_m2[i] = (a[a2 + i] << 2) - (a[a1 + i] << 1) + a[a0 + i];b_m2[i] = (b[b2 + i] << 2) - (b[b1 + i] << 1) + b[b0 + i];}// ==== c(-2) = a(-2) * b(-2)toom_cook3_process_01(a_m2, b_m2, out int[] c_m2);// ==== a(-1) = a2 - a1 + a0, b(-1) = b2 - b1 + b0for (int i = 0; i < n1; i++){a_m1[i] = a[a2 + i] - a[a1 + i] + a[a0 + i];b_m1[i] = b[b2 + i] - b[b1 + i] + b[b0 + i];}// ==== c(-1) = a(-1) * b(-1)toom_cook3_process_01(a_m1, b_m1, out int[] c_m1);// ==== a(0) = a0, b(0) = b0for (int i = 0; i < n1; i++){a_0[i] = a[a0 + i];b_0[i] = b[b0 + i];}// ==== c(0) = a(0) * b(0)toom_cook3_process_01(a_0, b_0, out int[] c_0);// ==== a(1) = a2 + a1 + a0, b(1) = b2 + b1 + b0for (int i = 0; i < n1; i++){a_1[i] = a[a2 + i] + a[a1 + i] + a[a0 + i];b_1[i] = b[b2 + i] + b[b1 + i] + b[b0 + i];}// ==== c(1) = a(1) * b(1)toom_cook3_process_01(a_1, b_1, out int[] c_1);// ==== a(inf) = a2, b(inf) = b2for (int i = 0; i < n1; i++){a_inf[i] = a[a2 + i];b_inf[i] = b[b2 + i];}// ==== c(inf) = a(inf) * b(inf)toom_cook3_process_01(a_inf, b_inf, out int[] c_inf);// ==== c4 = 6 * c(inf) / 6for (int i = 0; i < n2; i++){c4[i] = c_inf[i];}// ==== c3 = -c(-2) + 3 * c(-1) - 3 * c(0) + c(1) + 12 * c(inf) / 6for (int i = 0; i < n2; i++){c3[i] = -c_m2[i];c3[i] += (c_m1[i] << 1) + c_m1[i];c3[i] -= (c_0[i] << 1) + c_0[i];c3[i] += c_1[i];c3[i] += (c_inf[i] << 3) + (c_inf[i] << 2);c3[i] /= 6;}// ==== c2 = 3 * c(-1) - 6 * c(0) + 3 * c(1) - 6 * c(inf) / 6for (int i = 0; i < n2; i++){c2[i] = (c_m1[i] << 1) + c_m1[i];c2[i] -= (c_0[i] << 2) + (c_0[i] << 1);c2[i] += (c_1[i] << 1) + c_1[i];c2[i] -= (c_inf[i] << 2) + (c_inf[i] << 1);c2[i] /= 6;}// ==== c1 = c(-2) - 6 * c(-1) + 3 * c(0) + 2 * c(1) - 12 * c(inf) / 6for (int i = 0; i < n2; i++){c1[i] = c_m2[i];c1[i] -= (c_m1[i] << 2) + (c_m1[i] << 1);c1[i] += (c_0[i] << 1) + c_0[i];c1[i] += (c_1[i] << 1);c1[i] -= (c_inf[i] << 3) + (c_inf[i] << 2);c1[i] /= 6;}// ==== c0 = 6 * c(0) / 6for (int i = 0; i < n2; i++){c0[i] = c_0[i];}// ==== z = c4 * x^4 + c3 * x^3 + c2 * x^2 + c1 * x + c0for (int i = 0; i < n2; i++){z[i + n4] += c4[i];z[i + n3] += c3[i];z[i + n2] += c2[i];z[i + n1] += c1[i];z[i] += c0[i];}
}/// <summary>/// 乘积和的进位计算/// </summary>/// <param name="a"></param>/// <param name="n"></param>/// <exception cref="Exception"></exception>private static void toom_cook3_carry(int[] a, int n){int cr = 0;for (int i = 0; i < n; i++){a[i] += cr;if (a[i] < 0){cr = -(-(a[i] + 1) / 10 + 1);}else{cr = a[i] / 10;}a[i] -= cr * 10;}if (cr != 0){// Overflowthrow new Exception("OVERFLOW! cr=" + cr);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/112149.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebGL 视图矩阵、模型视图矩阵

目录 立方体由三角形构成 视点和视线 视点、观察目标点和上方向 视点&#xff1a; 观察目标点&#xff1a; 上方向&#xff1a; 在WebGL中&#xff0c;观察者的默认状态应该是这样的&#xff1a; 视图矩阵程序&#xff08;LookAtTriangles.js&#xff09; 实际上&…

【资源监视器】设备占用,强制弹出移动硬盘

设备占用&#xff0c;强制弹出移动硬盘 任务管理器中找到资源监视器 资源监视器&#xff1a;找到CPU 输入磁盘&#xff1a;如H: , 点击旁边的刷新 结束句柄 右键

python-字符串去掉空格的常见方法

python提供了去掉字符串空格的方法&#xff0c;可以满足大部分需求。 但在实际应用中&#xff0c;还需要灵活借助python其他方法&#xff0c;来实现字符串空格的删除。 比如&#xff0c;去掉字符串的全部空格、字符串连续空格保留一个等&#xff0c;都需要结合其他的方法来实现…

Postman接口压力测试 ---- Tests使用(断言)

所谓断言&#xff0c;主要用于测试返回的数据结果进行匹配判断&#xff0c;匹配成功返回PASS&#xff0c;失败返回FAIL。 下图方法一&#xff0c;直接点击右侧例子函数&#xff0c;会自动生成出现在左侧窗口脚本&#xff0c;只需修改数据即可。 方法二&#xff1a;直接自己写脚…

vue中slot,slot-scope,v-slot的用法和区别

slot用于设置标签的属性值(slot“title”)slot-scopev-slot slot <el-menu-item v-if"!navMenu.children" :key"navMenu.id" :index"navMenu.id " click"itemClick(navMenu)" ><span slot"title">{{ navMenu.…

UMA 2 - Unity Multipurpose Avatar☀️九.Expressions表情管理与表情插件推荐 (口型同步 / 表情管理)

文章目录 🟥 Expressions文件位置🟧 功能 : 解决嘴巴张开问题🟨 Expressions : 表情面板API讲解🟩 表情插件推荐 : 口型同步 / 表情管理🟥 Expressions文件位置 Expressions也是UMA内置5种实用Recipes之一,位置如下. 使用方法: 如下图所示,将Recipes拖到Additional…

数据结构-----队列

目录 前言 队列 定义 队列的定义和操作方法 队列节点的定义 操作方式 顺序表实现队列&#xff08;C/C代码&#xff09; 链表实现队列&#xff08;C/C代码&#xff09; Python语言实现队列 前言 排队是我们日常生活中必不可少的一件事&#xff0c;去饭堂打饭的时候排队&a…

实现数组去重的七种方法

实现数组去重的 7 种方式 1. 方法一&#xff1a;利用两层循环数组的splice方法 通过两层循环对数组元素进行逐一比较&#xff0c;然后通过splice方法来删除重复的元素。此方法对NaN是无法进行去重的&#xff0c;因为进行比较时NaN ! NaN。 let arr [1, 2, 2, abc, abc, true,…

LeetCode: 4. Median of Two Sorted Arrays

LeetCode - The Worlds Leading Online Programming Learning Platform 题目大意 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。 请你找出这两个有序数组的中位数&#xff0c;并且要求算法的时间复杂度为 O(log(m n))。 你可以假设 nums1 和 nums2 不会同时为空。 …

【笔试强训选择题】Day43.习题(错题)解析

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;笔试强训选择题 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&#xff…

[BJDCTF2020]Mark loves cat foreach导致变量覆盖

这里我们着重了解一下变量覆盖 首先我们要知道函数是什么 foreach foreach (iterable_expression as $value)statement foreach (iterable_expression as $key > $value)statement第一种格式遍历给定的 iterable_expression 迭代器。每次循环中&#xff0c;当前单元的值被…

【Unity插件】实现多人在线游戏——Mirror插件的使用介绍

文章目录 前言导入Mirror插件 简单介绍一、RPC调用二、错误注意 基本使用一、创建场景的网络管理器二、创建一个玩家三、添加玩家初始生成位置四、玩家控制五、同步摄像机六、同步不同角色的名字和颜色修改七、同步动画八、同步子弹方法一方法二 九、聊天功能十、场景同步切换十…