【问题标题】:How do I process the return value inf如何处理返回值 inf
【发布时间】:2019-02-20 05:42:14
【问题描述】:

我自己完成了一本关于 C 的书。这不是要上交的作业。我正在编写一个 C 程序来确定我的机器可以产生的最大斐波那契数。并指示使用非递归方法。

我的代码:

#include<stdio.h>
double fibo(int n);
int main(void)
{
    int n = 0; // The number input by the user
    double value; // Value of the series for the number input

    while (n >= 0)
    {

       // Call fibo function

       value = fibo(n);

       // Output the value

       printf("For %d the value of the fibonacci series = %.0f\n", n, 
       value);


       n++;

    }

   return 0;
}

double fibo(int n)
{

  int i; // For loop control variable
  double one = 0; // First term
  double two = 1; // Second term
  double sum = 0; // placeholder

  if (n == 0)
      return 0;
  else if (n == 1)
      return 1;
  else
  {
     for (i = 2; i <= n; i++)
     {
        sum = one + two;
        one = two;
        two = sum;
     }
  }

return sum;

代码工作正常,但是当输出给我第一个实例时我想中断:

For 17127 the value of the fibonacci series = inf

有没有办法给我们一个 if 语句,例如:

if (value == inf)
  break;

【问题讨论】:

  • main 函数中的那个循环,它应该什么时候结束?如果要添加 break 循环的特殊条件,为什么还要有条件循环呢?尤其是可能导致有符号整数算术溢出(这是未定义的行为)。
  • 不是。故意将其保留为无限,以查看数字有多大。我希望我能在出现特定值时让它停止
  • 理论上只是无限的。实际上,计算机上的所有整数值都是有限的。如前所述,C 中带符号整数的算术溢出(当您越过 int 的限制时,n++ 会发生这种情况)会导致未定义的行为。
  • 你可能至少应该检查一下 man(3) isinf() 和 fpclassify(),inf 不打算在你的代码中使用。
  • 很容易输入数字并使其停止。会做。谢谢

标签: c floating-point break


【解决方案1】:

最简单的是使用INFINITYisinf()

【讨论】:

    【解决方案2】:

    刚刚做了一点搜索,发现了这个不错的技巧:

    ...
    double value, temp; // Value of the series for the number input
    
    while (n >= 0)
    {
    
       // Call fibo function
    
       temp = fibo(n);
       if (temp - temp != 0)
            break;
       else
            value=temp;
    ...
    

    事实证明,当 temp 达到 Inf 时,如果条件 temp - temp 产生 Nan 等于什么都没有,其余的只是执行 break; 以退出进程。

    【讨论】:

    • 解释有误。这是因为Inf - Inf 产生Nan,它不等于一切,包括它自己。
    • @AlexeyFrunze 事实证明你是对的,没有必要对temps 之一进行类型转换。像(temp - temp != 0) 或只是(temp - temp != any_number) 这样的if 条件似乎可以完成这项工作,因为它们都产生Nan
    【解决方案3】:

    当输出给我第一个实例时,我想打破:inf

    只需对来自&lt;math.h&gt;INFINITY 进行测试。输出将不是精确 Fibonacci number

    #include <math.h>
    #include <stdio.h>
    
    int main(void) {
      double a;
      double b = 0;
      double c = 1;
      do {
        a = b;
        b = c;
        c = a + b;
      } while (c < INFINITY);
      printf("%e\n", b);
      return 0;
    }
    

    输出

    1.306989e+308
    

    long double

    使用最宽的浮点类型并寻找不精确的加法。

    #include <fenv.h>
    #include <stdio.h>
    
    int main(void) {
      long double a;
      long double b = 0;
      long double c = 1;
      do {
        a = b;
        b = c;
        c = a + b;
      } while (fetestexcept(FE_INEXACT) == 0);
      printf("%.0Lf\n", b);
      return 0;
    }
    

    输出

    12200160415121876738
    

    整数

    使用可用的最广泛的类型。这类似于@Syed.Warisunsigned long long 方法。虽然unsigned long longuintmax_t 具有相同的范围很常见,但使用uintmax_t 可以确保最宽。

    uintmax_t:以下类型表示无符号整数类型,能够表示任何无符号整数类型的任何值:

      #include <stdint.h>
      #include <stdio.h>
    
      uintmax_t a;
      uintmax_t b = 0;
      uintmax_t c = 1;
    
      do {
        a = b;
        b = c;
        c = a + b;
      } while(c >= b);
      printf("%ju\n", b);
    

    输出

    12200160415121876738
    

    字符串

    double 或某些int 类型的替代方法是创建一个简单的字符串添加函数str_add(),然后很容易形成斐波那契数.

    int main(void) {
      char fib[3][4000];
      strcpy(fib[0], "0");
      strcpy(fib[1], "1");
      int i;
      for (i = 2; i <= 17127 && strlen(fib[1])  < sizeof fib[1] - 1; i++) {
        printf("Fib(%3d) %s.\n", i, str_add(fib[2], fib[1], fib[0]));
        strcpy(fib[0], fib[1]);
        strcpy(fib[1], fib[2]);
      }
      printf("%zu\n", strlen(fib[2]));
      return 0;
    }
    

    输出

    Fib(1476) 13069...(299 digits)....71632.  // Exact max `double`
    Fib(17127) 95902...(3569 digits)...90818.
    

    【讨论】:

      【解决方案4】:

      我的机器可以产生的最大斐波那契数

      这个问题与任何数据类型无关,但与机器有关。

      斐波那契的基本规则是这样的:

      n = (n-1) + (n-2)

      您可以获取一个大的unsigned long long 变量,并且可以继续添加。但是,如果该数据类型溢出怎么办?您不关心数据类型。您的机器可能会产生比long long 更大的数字。那个数字是多少? RAM 上的所有位?硬盘?

      由于您需要使用迭代方法而不是递归方法,因此您的老师/书籍/讲师可能正在循环测试您(而不是任何标准 API)。下面是使用unsigned long long的示例代码:

      #include <stdio.h>
      
      int main ()
      {
      
        unsigned long long a = 0;
        unsigned long long b = 1;
      
        unsigned long long c = a + b;
      
      
        while(c >= b)
        {
           a = c;
           c = b + c;
           b = a;
        }
      
        printf("\n%llu\n", b);
      
        return 0;
      
      }
      

      输出:

      12200160415121876738

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-18
        • 1970-01-01
        • 1970-01-01
        • 2011-05-08
        • 2013-09-30
        • 1970-01-01
        • 2013-11-06
        • 2014-01-07
        相关资源
        最近更新 更多