【问题标题】:Dynamic Programming Issue - Fibonacci Sequence动态规划问题 - 斐波那契数列
【发布时间】:2012-09-06 22:56:47
【问题描述】:

我正在阅读this Wikipedia 文章,并尝试在 C 中实现基于“地图”的解决方案,其中“地图”只是一个初始化为 0 的 int 数组。

由于某种原因,它可以工作到fib(93),然后开始输出奇怪的数字。如果有关系,我指定-std=c99

#include <stdio.h>
#include <stdlib.h>

// represents a fib num
typedef unsigned long long fib_t;

// the default value of our 'map'
const int FIB_NULL   = 0;

// could get from input, set here for now
const int FIB_MAX    = 100;

// our 'map' for fib nums
static fib_t *fibMap;

// calculate the fib num n
fib_t fib( unsigned int n )
{
    // if this num, n, is not 0 or 1, and is FIB_NULL, then calculate it
    if( n > 1 && FIB_NULL == fibMap[n] )
    {
        fibMap[n] = fib( n-1 ) + fib( n-2 );
    }

    // get it from the map
    return fibMap[n];
}

// used to setup the 'map' for the fibs
static void initFibMap()
{
    // emulate a map
    fibMap = malloc( sizeof(fib_t) * FIB_MAX);

    // initialize it to 'null'
    memset(fibMap, FIB_NULL, sizeof(fib_t) * FIB_MAX);

    // by definition
    fibMap[0] = 0;
    fibMap[1] = 1;
}

int main(int argc, char *argv[]) 
{
    // setup our 'map'
    initFibMap();

    for( unsigned int i=0; i<FIB_MAX; i++ )
    {
        // breaks on 94
        printf("Fib #%d: %llu\n",i, fib(i));
    }
}

奇怪的输出:

// . . .
// . . .
// Fib #90: 2880067194370816120  // good
// Fib #91: 4660046610375530309  // good
// Fib #92: 7540113804746346429  // good
// Fib #93: 12200160415121876738 // good
// Fib #94: 1293530146158671551  // WHAT?
// Fib #95: 13493690561280548289
// Fib #96: 14787220707439219840
// Fib #97: 9834167195010216513
// Fib #98: 6174643828739884737
// Fib #99: 16008811023750101250

【问题讨论】:

  • 确实意识到你连unsigned long long right都溢出了?
  • @Mystical:我没有,我以前从未处理过这么大的数字。快速访问limit.h #ULONG_MAX 表明您确实是正确的。有关解决此问题的任何建议?
  • 不幸的是,C 没有对 bignums 的原生支持。因此,您需要自己编写或使用 GMP 等库。如果您愿意牺牲精度,那么使用浮点数可能是可以接受的。
  • @Josh 你可以使用一些大数字支持库——例如,GNU bigint。
  • @Mysticial:非常感谢。我不需要任何精确度等,这只是一个学习练习。但我会牢记这一点,以备不时之需。

标签: c dynamic-programming fibonacci unsigned-long-long-int


【解决方案1】:

对于如此大的数字,您会得到一个无符号整数溢出,这会导致“环绕”导致运算的原始结果,以 1 &lt;&lt; bits 为模,位是特定整数类型的位宽。如果要表示这些数字,则必须使用某种 bignum 库,例如 GNU GMP.

【讨论】:

  • 无符号整数在产生超出范围结果的计算中的行为完全由标准定义,它是算术模2^WIDTH
【解决方案2】:

随着数字越来越大,整数越来越溢出,所以“环绕”正在发生 所以你可以使用 GNU GMP 库或使用字符串来表示数字,就像我对大数的阶乘所做的那样 链接到http://codepad.org/bkWNV0JC

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 2020-07-16
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    相关资源
    最近更新 更多