деление небольшого положительного числа с плавающей запятой двойной точности на большое положительное число, дающее мне отрицательный результат - PullRequest
0 голосов
/ 25 января 2019

Я пишу код на C, который анализирует постоянный фактор сложности времени всех методов сортировки.Я включаю статистическое исследование этих констант.Для этого мне нужно было найти соотношение двух положительных двойных чисел.Удивительно, но я получаю отрицательный результат.Может ли кто-нибудь помочь мне понять, чего мне здесь не хватает?

Я начал копаться в вики https://en.wikipedia.org/wiki/C_data_types и в этом https://www.geeksforgeeks.org/data-types-in-c/,, но, похоже, нет ответа, который я ищу.

#include <stdio.h>

int main(void) {
    // your code goes here
    int i=1500;
    double j=9265.49;
    double result=(double)j/((double)(i*i*i*i));
    printf("%lf",result);
    return 0;
}

Результат -0,000007, что явно неверно.

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Целочисленное переполнение:

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

int main(int argc, char *argv[]) {
  int      i   = 1500;
  int32_t  i32 = 1500;
  uint32_t u32 = 1500;

  printf("i  : %lf\n", (double)(i*i*i*i));
  printf("i32: %lf\n", (double)(i32*i32*i32*i32));
  printf("u32: %lf\n", (double)(u32*u32*u32*u32));

  long int li  = 1500;
  int64_t  i64 = 1500;
  uint64_t u64 = 1500;

  printf("li : %lf\n", (double)(li*li*li*li));
  printf("i64: %lf\n", (double)(i64*i64*i64*i64));
  printf("u64: %lf\n", (double)(u64*u64*u64*u64));

  return(0);
}

Вывод на мой Linux x86_64 с GCC 8:

$ ./dummy 
i  : -1266441984.000000
i32: -1266441984.000000
u32: 3028525312.000000
li : 5062500000000.000000
i64: 5062500000000.000000
u64: 5062500000000.000000
0 голосов
/ 25 января 2019

int переполнение

i*i*i*i - это int математика и int переполнение 1 , что составляет неопределенное поведение (UB). @ Евгений Ш.

В случае OP, i*i*i*i -> стал -1266441984 или около того.


Избегайте переполнения при умножении. Выполните умножение с более широкой математикой.

int main(void) {
  int i = 1500;
  double j = 9265.49;
  // double result=(double)j/((double)(i*i*i*i));
  double result = (double) j / ((double) i * i * i * i);
  printf("%e", result);
  return 0;
}

выход

1.830220e-09

См. Есть причины не использовать 1000 *1000* 1000 для получения дополнительной информации о коде, например i*i*i*i.


1 При INT_MAX < 5062500000000 как с 32-битным int.

...