【问题标题】:Checking for unsigned long long overflow检查无符号长长溢出
【发布时间】:2015-10-19 21:02:48
【问题描述】:

我正在尝试生成斐波那契数,并将它们存储为无符号长整数。但是,如果系列中的新数字大于 unsigned long long 可以容纳的数字,我希望停止生成更多数字。我目前有以下。

unsigned long long n1 = 1, n2 = 1, n3;
    int i;
    for(i = 0; i < n; i++) {
        if(i == 0 || i == 1) {
            fprintf(fibonacci_file, "%lld\n", n1);
        }else {
            n3 = n1 + n2;
            if(n3 < n1) {
                printf("FIBONACCI OVERFLOW\n");
                break;
            }else {
                fprintf(fibonacci_file, "%lld\n", n3);
                n1 = n2;
                n2 = n3;
            }
        }
    }

那么输出文件的结尾是这样的。

1100087778366101931
1779979416004714189
2880067194370816120
4660046610375530309
7540113804746346429
-6246583658587674878

最后一个是负数,表示结果溢出。但是我的支票应该已经抓住了它而不是打印出来,并结束了循环。

【问题讨论】:

  • %lld 更改为%llu。计算没问题,只是打印格式不对。
  • 在求和 n3 = n1 + n2 之前最好是 if (ULLONG_MAX - n2 &lt; n1),以防止溢出。
  • 请注意,有符号整数溢出是未定义的行为,必须避免。就像将无符号整数转换为不能保存该值的有符号整数一样。无符号整数溢出 otoh 是明确定义的,但您应该非常小心,不要在链中包含有符号整数。
  • 哇,谢谢!花了这么长时间试图修复它,以为我的逻辑是错误的。甚至不认为这只是格式。

标签: c overflow long-integer unsigned addition


【解决方案1】:

错误的说明符用于打印unsigned long long 的全部范围。使用"%llu"@void_ptr

unsigned long long n3;
....
// fprintf(fibonacci_file, "%lld\n", n3);
fprintf(fibonacci_file, "%llu\n", n3);

OP 检测溢出的方法与 C 中的一样好,数学溢出被很好地定义为简单地“换行”。那是伪代码:unsigned_sum = math_sum mod (UMAX+1) 给定所涉及类型的最大值。

 if (n3 < n1) {
   printf("FIBONACCI OVERFLOW\n");
   break;

已删除的讨论还提出了一个惯用测试@Weather Vane@Olaf,这也可以工作。当涉及的类型不是无符号整数,而是有符号整数或浮点数时,这种方法很有用。

 if (ULLONG_MAX - n2 < n1) {
   printf("FIBONACCI OVERFLOW\n");
   break;
 }
 n3 = n1 + n2;

此外,该系列有时被认为是从F[0] = 0 开始的。见Fibonacci number

【讨论】:

    猜你喜欢
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-10
    • 2020-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多