长期超出范围

时间:2015-10-28 00:44:13

标签: c

我有以下问题。执行此代码时,变量lonpk的值超出了long int值的限制,程序打印的值不正确。问题在于计算加起来为100的数字立方

#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <conio.h>
void main(void){

for (long i = -2000; i <= 2000; i++) {
        long pi = i * i * i;
        if ((i > 0) && (pi > 100)) {
            break;
        }
        for (long j = i; j <= 2000; j++) {
            long pj = (pi + (j * j * j));
            if ((j > 0) && (pj > 100)) {
                break;
            }
            for (long k = j; k <= 2000; k++) {
                long pk = pj + (k * k * k);
                if ((k > 0) && (pk > 100)) {
                    break;
                }

                if (pk == 100.0) {
                    printf("%ld",pk);
                    printf("primer numero=%ld segundo numero=%ld  tercer numero=%ld\n",i,j,k);

                }
            }
        }
   }
    getch();
}

错误的结果

    primer numero=-1971 segundo numero=-986  tercer numero=295    
correct result    
    primer numero=-1797 segundo numero=1870  tercer numero=-903

1 个答案:

答案 0 :(得分:1)

使用long long进行数学运算,因为它具有pow(2000,3)所需的范围。

请注意下面的代码行。第一个可以溢出,假设ULNG_MAX == 2**32 - 1,而第二个,通过乘以1LL强制long long数学来使用 - = - 至少是64位。

 long i;
 i * i * i
 1LL * i * i * i

代码:

for (long i = -2000; i <= 2000; i++) {
        long long pi = 1LL * i * (i * i);
        if ((i > 0) && (pi > 100)) {
            break;
        }
        for (long j = i; j <= 2000; j++) {
            long long pj = (pi + (1LL*j * (j * j)));
            if ((j > 0) && (pj > 100)) {
                break;
            }
            for (long k = j; k <= 2000; k++) {
                long long pk = pj + (1LL * k * (k * k));
                if ((k > 0) && (pk > 100)) {
                    break;
                }

                if (pk == 100) {
                    printf("%lld",pk);
                    printf("primer numero=%ld segundo numero=%ld  tercer numero=%ld\n"
                        ,i,j,k);

                }
            }
        }
   }
    getch();
}

OP无法访问long long,然后使用{em>可能具有足够范围/精度的double来执行此任务。

int main(void) {
  for (long i = -2000; i <= 2000; i++) {
    double pi = 1.0 * i * (i * i);
    if ((i > 0) && (pi > 100)) {
      break;
    }
    for (long j = i; j <= 2000; j++) {
      double pj = (pi + (1.0 * j * (j * j)));
      if ((j > 0) && (pj > 100)) {
        break;
      }
      for (long k = j; k <= 2000; k++) {
        double pk = pj + (1.0 * k * (k * k));
        if ((k > 0) && (pk > 100)) {
          break;
        }

        if (pk == 100) {
          printf("%.0f", pk);
          printf("primer numero=%ld segundo numero=%ld  tercer numero=%ld\n", i, j, k);
          fflush(stdout);
        }
      }
    }
  }
  getch();
  return 0;
}

100primer numero=-1797 segundo numero=-903  tercer numero=1870
100primer numero=-161 segundo numero=-139  tercer numero=190
100primer numero=-6 segundo numero=-3  tercer numero=7

[编辑]主要加速 - 减少for(k),可能快50倍

  // k*k*k + pj = 100;
  // k = pow(100 - pj, 1.0/3)
  long kmin = (long) pow(100 - pj, 1.0/3) - 1;
  if (kmin < j) kmin = j;
  for (long k = kmin; k <= 2000; k++) {
    double pk = pj + (1.0 * k * k * k);
    if ((k > 0) && (pk > 100)) {
      break;
    }