Sabarna Hazra
Sabarna Hazra

Reputation: 43

dividing a small positive double-precision floating-point number by a large positive number giving me negative result

I am writing a code in C which analyzes the constant factor of time complexity of all sorting techniques. I am including a statistical study of those constants. To do that I had to find the ratio of two positive double numbers. Surprisingly I am getting a negative result. Could anybody help me understand what I am missing here?

I started digging in wiki https://en.wikipedia.org/wiki/C_data_types and this https://www.geeksforgeeks.org/data-types-in-c/, but that does not seem to have the answer I am looking for.

#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;
}

The result is -0.000007 which is clearly wrong.

Upvotes: 0

Views: 67

Answers (2)

chux
chux

Reputation: 153338

int overflow

i*i*i*i is int math and int overflow1 which is undefined behavior (UB). @Eugene Sh.

In OP's case, i*i*i*i --> became -1266441984 or so.


Avoid overflow in the multiplication. Perform the multiplication with wider math.

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;
}

Output

1.830220e-09

See There are reasons not to use 1000 * 1000 * 1000 for additional insights about code such as i*i*i*i.


1 When INT_MAX < 5062500000000 as with 32-bit int.

Upvotes: 3

Stefan Becker
Stefan Becker

Reputation: 5952

Integer overflow:

#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);
}

Output on my Linux x86_64 with GCC 8:

$ ./dummy 
i  : -1266441984.000000
i32: -1266441984.000000
u32: 3028525312.000000
li : 5062500000000.000000
i64: 5062500000000.000000
u64: 5062500000000.000000

Upvotes: 1

Related Questions