大整数乘法
本文最后更新于69 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

算法思想:通过减少乘法次数来提高效率。

算法步骤:

  • 假设我们要计算两个大整数 x 和 y 的乘积,可以将 x 和 y 分别表示为:
    • x=a⋅10m+b
    • y=c⋅10m+d
  • 其中 aa 和 bb 是 xx 的高 m 位和低 m 位,c 和 d 是 y 的高 m 位和低 m 位。那么:
    • x⋅y=(a⋅10m+b)⋅(c⋅10m+d) =ac⋅102m+(ad+bc)⋅10m+bd
    • 这种传统算法我们需要计算ac, adad, bcbc, 和 bdbd,共 4 次乘法。

Karatsuba 算法通过以下步骤减少乘法次数:

    • 计算 z2=ac
      • 计算高 m 位的乘积。
    • 计算 z0=bd
      • 计算低 m 位的乘积。
    • 计算 z1=(a+b)⋅(c+d)
      • 计算 (a+b)(a+b) 和 (c+d)(c+d) 的乘积。
    • 计算 (z1−z2−z0)⋅10m
      • 通过 z1​ 减去 z2​ 和 z0​,得到 ad+bc 的值。
    • 最终结果
      • 组合上述结果,得到最终的乘积: x⋅y=z2⋅102m+(z1−z2−z0)⋅10m+z0

经过这样的修改之后Karatsuba 算法只需要3次乘法z1​ 、 z2​ 和 z0​就可以算出结果。

代码:

主方法:在main方法中,定义了大整数x和y,调用karatsuba方法来计算他们的乘积。

public static void main(String[] args){
//用户在屏幕上输入数字
System.out.println("请输入两个数:");
Scanner sc = new Scanner(System.in);
String x = sc.next();
String y = sc.next();
// String x = "123456789";
// String y = "987654321";
System.out.println(karatsuba(x,y));
}

karatsuba方法:

  • 首先是判断其中一个数的长度是否为1,如果为1那就可以直接返回结果。
  • 确保长度相同:通过在较短的字符串前面补零,使得两个字符串的长度相同并且都为偶数。padLeft 方法用于在字符串前面补零。
  • 分割字符串:将每个字符串分成两部分,分别表示高m位和低m位。m是字符串长度的一半。
  • 递归调用
    • 计算 z2=a⋅c
    • 计算 z0=b⋅d
    • 计算 z1=(a+b)⋅(c+d)
  • 组装结果:
    • 计算 (z1−z2−z0)⋅10m
    • 最终结果为 x⋅y=z2⋅102m+(z1−z2−z0)⋅10m+z0
public static String karatsuba(String  x, String y){
    //当一个数的长度为1,则直接返回他们的乘积。
    if(x.length() == 1 || y.length()==1){
        return String.valueOf(Long.parseLong(x) * Long.parseLong(y));
    }
    //确保两个数的长度相同并且为偶数
    int n = Math.max(x.length(),y.length());
    //确保n是偶数
    n = n % 2 == 0 ? n : n+1;
    x = padLeft(x, n);
    y = padLeft(y, n);
    //分割字符串.substring 是 Java 中 String 类的一个内置方法,用于获取字符串的一部分。
    int m = n/2;
    String a = x.substring (0, m);//表示获取字符串x的前m个字符,即从索引0到m-1(包含m-1)。
    String b = x.substring(m);//表示获取字符串x的后m个字符,即从索引m开始到最后。
    String c = y.substring(0, m);
    String d = y.substring(m);
    // 递归计算 z2, z0, z1
    String z2 = karatsuba(a, c); // z2 = a * c
    String z0 = karatsuba(b, d); // z0 = b * d
    String z1 = karatsuba(add(a, b), add(c, d)); // z1 = (a + b) * (c + d)

    // 计算 (z1 - z2 - z0) * 10^m
    String part1 = multiplyByPowerOf10(z2, 2 * m);
    String part2 = multiplyByPowerOf10(subtract(subtract(z1, z2), z0), m);
    String part3 = z0;

    // 组装最终结果
    return add(add(part1, part2), part3);
}

辅助方法:

  • padLeft:在字符串前面补零,使其达到指定长度。
  • add 和 subtract:使用 Long.parseLong 将字符串转换为长整数,进行加法和减法操作。
  • multiplyByPowerOf10:将字符串乘以 1010 的幂次方,通过在末尾添加零实现。
// 字符串加法
private static String add(String a, String b) {
return String.valueOf(Long.parseLong(a) + Long.parseLong(b));
}

// 字符串减法
private static String subtract(String a, String b) {
return String.valueOf(Long.parseLong(a) - Long.parseLong(b));
}
// 将字符串乘以 10 的幂次方
private static String multiplyByPowerOf10(String s, int power) {
StringBuilder sb = new StringBuilder(s);
for (int i = 0; i < power; i++) {
sb.append('0');
}
return sb.toString();
}
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇