搜索
首页web前端js教程使用快速傅里叶变换 (FFT) 乘以大十进制数

Multiplying Large Decimal Numbers Using Fast Fourier Transform (FFT)

介绍

将大十进制数相乘可能在计算上具有挑战性,尤其是在处理具有许多位数或多个小数位的数字时。传统的乘法方法对于极大的数字来说效率很低。这就是快速傅里叶变换 (FFT) 发挥作用的地方,它提供了一种强大而高效的算法,可以以惊人的速度进行大数相乘。

乘法中的应用

  • FFT 通过将数字变换到频域、执行逐点乘法,然后应用逆 FFT 来实现多项式或大整数的快速乘法。

大数乘法的挑战

传统乘法方法的时间复杂度为 O(n²),其中 n 是位数。对于非常大的数字,这在计算上变得昂贵。基于 FFT 的乘法算法将这种复杂性降低到 O(n log n),使得处理大数的速度显着加快。

Cooley-Tukey FFT 的证明大纲

  1. 离散傅立叶变换 (DFT) 的分解:

    • DFT 定义为:
      Xk=Σn=0N1 xne2π ikn/N,X_k = sum_{n=0}^{N-1} x_n cdot e^{-2pi i cdot kn / N}, Xk = n=0ΣN−1 xne−2πi⋅kn /N,
      在哪里 NN N 是输入信号的大小。
    • Cooley-Tukey FFT 将计算分解为更小的 DFT N/2N/2 N/2 通过分离偶数索引和奇数索引项:
      Xk=Σn=0N/2 1x2ne2πi (2n )k/N Σn=0N / 21x2 n 1e2 πi(2n 1)k/NX_k = sum_{n=0}^{N/2-1} x_{2n} cdot e^{-2pi i cdot (2n)k / N} sum_{n=0}^{N/2-1} x_{2n 1} cdot e^{-2pi i cdot (2n 1)k / N}。 Xk = n=0ΣN/2−1x2n e −2πi⋅(2n)k/N n=0ΣN/ 2−1x2n 1e−2πi⋅(2n 1)k/N.
    • 这减少为:
      Xk=偶数项的 DFT Wk奇数项的 DFT, X_k = text{偶数项的DFT} W_k cdot text{奇数项的DFT}, Xk =偶数项的 DFT Wk奇数项的 DFT,
      在哪里 Wk=e2πik/N W_k = e^{-2pi i cdot k / N} Wk =e−2πi ⋅k/N .
  2. 递归结构:

    • 每个大小的 DFT NN N 被分成两个大小的 DFT N/2N/2 N/2 ,导致递归结构。
    • 这种递归除法一直持续到大小的基本情况 N=1N = 1 N=1 ,此时 DFT 只是输入值。
  3. 蝴蝶操作:

    • 该算法使用蝶形运算合并较小 DFT 的结果:
      a=u Wkv ,b=uWkv,a' = u W_k cdot v,四边形 b' = u - W_k cdot v, 一个=u Wkv,b =u−Wkv,
      在哪里 uu u vv v 是较小 DFT 的结果, WkW_k Wk 代表团结的根源。
  4. 位反转排列:

    • 输入数组根据索引的二进制表示重新排序,以实现就地计算。
  5. 时间复杂度:

    • 在每一层递归中,都有 NN N 涉及单位根的计算,递归的深度是 日志2(N)log_2(N) log2 (N) .
    • 这会产生时间复杂度 O(N logNO(N log N) O(NlogN) .

逆FFT

  • 逆 FFT 类似,但使用 e2πi kn/Ne^{2pi i cdot kn / N} e 2πi⋅kn/N 作为基础并对结果进行缩放 1/N1/N 1/N .

了解 FFT 乘法算法

FFT 乘法算法的工作原理有几个关键步骤:

  1. 预处理数字

    • 将输入数字转换为数字数组
    • 同时处理整数和小数部分
    • 将数组填充到最接近的 2 次幂以进行 FFT 计算
  2. 快速傅立叶变换

    • 使用 FFT 将数字数组转换为频域
    • 这将乘法问题转化为频域中更简单的逐点乘法
  3. 频域乘法

    • 对转换后的数组执行逐元素乘法
    • 利用复数运算进行高效计算
  4. 逆FFT和结果处理

    • 将相乘后的数组变换回时域
    • 处理数字进位
    • 重构最终的十进制数

实施的关键组成部分

复数表示

class Complex {
  constructor(re = 0, im = 0) {
    this.re = re;  // Real part
    this.im = im;  // Imaginary part
  }

  // Static methods for complex number operations
  static add(a, b) { /* ... */ }
  static subtract(a, b) { /* ... */ }
  static multiply(a, b) { /* ... */ }
}

Complex 类对于执行 FFT 运算至关重要,它使我们能够操作实域和虚域中的数字。

快速傅立叶变换函数

function fft(a, invert = false) {
  // Bit reversal preprocessing
  // Butterfly operations in frequency domain
  // Optional inverse transformation
}

FFT函数是算法的核心,有效地在时域和频域之间进行数字转换。

处理小数

该实现包括处理十进制数的复杂逻辑:

  • 分隔整数和小数部分
  • 跟踪小数点总数
  • 使用正确的小数点位置重建结果

示例用例

// Multiplying large integers
fftMultiply("12345678901234567890", "98765432109876543210")

// Multiplying very large different size integers
fftMultiply("12345678901234567890786238746872364872364987293795843790587345", "9876543210987654321087634875782369487239874023894")

// Multiplying decimal numbers
fftMultiply("123.456", "987.654")

// Handling different decimal places
fftMultiply("1.23", "45.6789")

// Handling different decimal places with large numbers
fftMultiply("1234567890123456789078623874687236487236498.7293795843790587345", "98765432109876543210876348757823694.87239874023894")

性能优势

  • 时间复杂度:O(n log n) 与传统方法的 O(n²) 相比
  • 精度:处理具有多个小数位的极大数字
  • 效率:大量乘法运算速度明显加快

限制和注意事项

  • 需要额外的内存来表示复数
  • 浮点运算会影响精度
  • 与传统乘法相比,实现更复杂

结论

FFT 乘法算法代表了一种有效地乘以大数的强大方法。通过利用频域变换,我们可以以惊人的速度和精度执行复杂的数学运算。

实际应用

  • 科学计算
  • 财务计算
  • 密码学
  • 大规模数值模拟

进一步阅读

  • Cooley-Tukey FFT 算法
  • 数论
  • 计算数学

代码

完整的实现如下,为使用快速傅里叶变换方法乘以大十进制数提供了一个强大的解决方案。

/**
 * Fast Fourier Transform (FFT) implementation for decimal multiplication
 * @param {number[]} a - Input array of real numbers
 * @param {boolean} invert - Whether to perform inverse FFT
 * @returns {Complex[]} - Transformed array of complex numbers
 */
class Complex {
  constructor(re = 0, im = 0) {
    this.re = re;
    this.im = im;
  }

  static add(a, b) {
    return new Complex(a.re + b.re, a.im + b.im);
  }

  static subtract(a, b) {
    return new Complex(a.re - b.re, a.im - b.im);
  }

  static multiply(a, b) {
    return new Complex(a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re);
  }
}

function fft(a, invert = false) {
  let n = 1;
  while (n > 1;
    for (; j & bit; bit >>= 1) {
      j ^= bit;
    }
    j ^= bit;
    if (i > 1;
    for (let i = 0; i  {
    const [intPart, decPart] = numStr.split(".");
    return {
      intPart: intPart || "0",
      decPart: decPart || "",
      totalDecimalPlaces: (decPart || "").length,
    };
  };

  const parsed1 = parseNumber(num1);
  const parsed2 = parseNumber(num2);

  // Combine numbers removing decimal point
  const combinedNum1 = parsed1.intPart + parsed1.decPart;
  const combinedNum2 = parsed2.intPart + parsed2.decPart;

  // Total decimal places
  const totalDecimalPlaces =
    parsed1.totalDecimalPlaces + parsed2.totalDecimalPlaces;

  // Convert to digit arrays (least significant first)
  const a = combinedNum1.split("").map(Number).reverse();
  const b = combinedNum2.split("").map(Number).reverse();

  // Determine result size and pad
  const resultSize = a.length + b.length;
  const fftSize = 1  new Complex(x, 0));
  const complexB = b.map((x) => new Complex(x, 0));

  // Perform FFT
  const fftA = fft(complexA);
  const fftB = fft(complexB);

  // Pointwise multiplication in frequency domain
  const fftProduct = new Array(fftSize);
  for (let i = 0; i = 10) {
      result[i + 1] += Math.floor(result[i] / 10);
      result[i] %= 10;
    }
  }

  // Remove leading zeros and convert to string
  while (result.length > 1 && result[result.length - 1] === 0) {
    result.pop();
  }

  // Insert decimal point
  const resultStr = result.reverse().join("");
  if (totalDecimalPlaces === 0) {
    return resultStr;
  }

  // Handle case where result might be shorter than decimal places
  if (resultStr.length 



<h3>
  
  
  输出
</h3>



<pre class="brush:php;toolbar:false">// Example Usage - Self verify using Python
console.log(
  "Product of integers:",
  fftMultiply("12345678901234567890", "98765432109876543210")
);
console.log("Product of decimals:", fftMultiply("123.456", "987.654"));
console.log("Product of mixed decimals:", fftMultiply("12.34", "56.78"));
console.log(
  "Product with different decimal places:",
  fftMultiply("1.23", "45.6789")
);
console.log(
  "Product with large integers:",
  fftMultiply(
    "12345678901234567890786238746872364872364987293795843790587345",
    "9876543210987654321087634875782369487239874023894"
  )
);
const num1 = "1234567890123456789078623874687236487236498.7293795843790587345";
const num2 = "98765432109876543210876348757823694.87239874023894";
console.log("Product:", fftMultiply(num1, num2));
Product of integers: 1219326311370217952237463801111263526900
Product of decimals: 121931.812224
Product of mixed decimals: 700.6652
Product with different decimal places: 56.185047
Product with large integers: 121932631137021795232593613105722759976860134207381319681901040774443113318245930967231822167723255326824021430
Product: 121932631137021795232593613105722759976860134207381319681901040774443113318245.93096723182216772325532682402143

以上是使用快速傅里叶变换 (FFT) 乘以大十进制数的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
了解JavaScript引擎:实施详细信息了解JavaScript引擎:实施详细信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python vs. JavaScript:学习曲线和易用性Python vs. JavaScript:学习曲线和易用性Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

Python vs. JavaScript:社区,图书馆和资源Python vs. JavaScript:社区,图书馆和资源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

从C/C到JavaScript:所有工作方式从C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

JavaScript引擎:比较实施JavaScript引擎:比较实施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

超越浏览器:现实世界中的JavaScript超越浏览器:现实世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

使用Next.js(后端集成)构建多租户SaaS应用程序使用Next.js(后端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

如何使用Next.js(前端集成)构建多租户SaaS应用程序如何使用Next.js(前端集成)构建多租户SaaS应用程序Apr 11, 2025 am 08:22 AM

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境