使用 C++ 查找第 1500000 个斐波那契数
Finding the 1500000th Fib Number Using C++
我写了以下代码来查找第 1500000 个斐波那契数(请忽略可怕的缩进,我在大约 2 分钟内写了这个)。我需要它作为字符串。假设这应该有效:
#include <cstdlib>
#include <iostream>
#include <sstream>
int i;
int b=1;
int c=2;
using namespace std;
int main(int argc, char *argv[])
{
int fib=1500000;
for (i=1;i<fib-3;i++){
c=b+c;
b=c-b;
}
stringstream ss;
ss << c;
string d=ss.str();
cout << d << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
它经历了1500000-3次的过程(每次超过3个数字)我知道问题是这个数字太大,不能作为一个整数来包含。有没有办法让我在不将其包含为 int 或文件的情况下存储它(因为那效率极低)?如果是这样,我该怎么做?
使用 Bignum 库。
如果您需要一个确切的形式,则可以对 bignum 库使用其他递归关系之一:
fib(2*n) = fib(n)^2 + fib(n-1)^2
fib(2*n-1) = fib(n)*(2*fib(n-1)+fib(n))
这应该减少所需的计算次数到O(log(n))而不是O(n)您可以在此处查看基于此方法的伪代码:亚线性时间中的第 n 个斐波那契数
请注意,第 n^ 个斐波那契数需要大约 n*log(phi)/log(2) = n*0.69 个二进制数字来表示,因此 1.5M^th 的精确表示将需要大约 130kb 以二进制表示,或 300kb 表示为字符串(大约为 2^(10000000) 或 10^(300000) )
在大约 n=1500 时作为双倍溢出删除
你可以直接使用双精度来做到这一点,如下所示(改编自 http://en.wikipedia.org/wiki/Fibonacci_number):
double fib( int n )
{
static const SQRT_5 = sqrt(5.0);
static const phi = (1.0+SQRT_5)/2.0;
return floor( (pow(phi,n)/SQRT_5) + 0.5 );
}
虽然如果你需要每个数字,这是行不通的。(它只会给出大约第 78 个斐波那契数的每个数字)
Boost 使使用 bignums 变得非常容易。
#include <boost/multiprecision/cpp_int.hpp>
typedef boost::multiprecision::cpp_int integer;
integer fibonacci( unsigned long long n )
{
integer a = 0;
integer b = 1;
while (n --> 0)
{
integer c = a + b;
a = b;
b = c;
}
return a;
}
#include <iostream>
#include <string>
int main( int argc, char ** argv )
try
{
long long n = std::stoll( argc == 2 ? argv[1] : "" );
if (n < 0) throw 1;
std::cout << fibonacci( n ) << "n";
}
catch (...)
{
std::cerr <<
"usage: n"
" fibonacci N n"
"where N is the Fibonacci number to compute.n";
return 1;
}
在上面的例子中,我使用了原生的 Boost bignum 类型,即:
- 仅标头(无需编译 Boost!
- 非常快
— 我在古老的 AMD 闪龙 130 上用大约两分钟计算斐波那契 (1500000)。如果我敲掉一个零,结果几乎是瞬间的。
如果这对您来说还不够快,Boost Multiprecision 还提供以下后端:
- GNU GMP
这是目前最好的 bignum 库,几乎在所有严肃的 bignum 计算环境中使用,但它受到 copyleft 的阻碍,并且众所周知很难正确设置。 - libTomMath
这更容易安装,但你仍然必须知道你在做什么。
第 1500000 个斐波那契数列在 C99 中,使用这个答案,只需更改一下:
#define BUFFER_SIZE 18935
没有库,输出应该是(313,482位):
129089216811873951612785 ... 853738956168354898000000
took 59s
f(1500000) 的计算也花了 30 秒和基本转换,所以大约一分钟。
1963年,Stephen P. Geller使用IBM 1620计算机显示,最后四位数字每15,000次重复一次,最后五位数字每150,000次重复一次,最后,在计算机运行近三个小时后,最后六位数字的重复出现在第1,500,000个斐波那契数上。
在线尝试f(15000) - 谢谢。
你确定C++
快吗?
gawk -v _____='1500000' -v PREC=20000 -p- -Mbe '
BEGIN {
1 _ += ___ = _ ^= ____ = __ = _ < _
1 _____ += ___
1 ____ = --_____
1 do {
1 print __ = length(_ = fib(____)), substr(_, 1, 50), substr(_, __ + 1 - 50)
} while (++____ < _____)
}
1 function fib(______, _, __, ___, ____, _____)
{
1 if ((______ = +_ < ______ ? +______ : +_) < (__ *= (__ = _ ~ _) + (++__))) {
return (______ - ((! _) < (______ % --__)))
}
1 _____ = (___ = __ = (_ = _ < _) ~ _) + ___
20 while ((___ += ___) <= ______) {
20 ++____
}
21 do {
21 __ = (__ * __ + _ * _) substr(_ *= __ + __ - _, ___, ! ___)
21 if (int(______ / (___ /= _____)) % _____) { # 10
10 __ = (__ + _) substr(_ = __, ___, ! ___)
}
} while (____--)
1 return _
}
( gawk -v _____='1500000' -v PREC=20000 -p- -Mbe ; ) 0.10s user 0.01s system 95% cpu 0.115 total
313482 12908921681187395161278531776694736120150441703840
02113051432895630172796932853738956168354898000000
*到底怎么C++
花了 59.0 秒awk
需要 0.115 秒
- 正在查找文档以获得PS4平台的C++中的设备信息
- 在C++中查找文件
- 模板元程序查找相似的连续类型名称
- 在UNIX系统中使用DIR查找文件的字节大小
- 查找最接近的大于当前数字的数字的索引
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 查找后更改类变量
- 使用正则表达式regex_search在字符串中查找字符串
- 使用gcc从静态链接的文件中查找可选符号
- 在C++中查找范围的长度
- 算法问题:查找从堆栈中弹出的所有序列
- 在Windows中查找扬声器输出的当前音量级别
- 如何在C++中使用X509证书模在令牌中查找私钥
- 使用.find函数在c++中查找字符和另一个字符之间的大小
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 在 for 循环中查找问题时遇到困难
- 如何在文件中查找字节序列
- 试图创建一个多线程程序来查找0-100000000之间的总素数
- 使用堆查找第K个最大元素的时间复杂性
- 一个函数,用于查找字符串1包含字符串2 c++的次数