1

I am writing a C program on a Linux box. I am trying to convert a command line argument to a double and then check if that number is larger than MAX_K. It it is larger, I want the program to exit, but it doesn't. For example, I set MAX_K to 10^18 and then put in 1000000000000000001 as the argument and if it is larger then 1000000000000000000 then I want the program to exit, otherwise print "OK", but the program doesn't exit but prints "OK". I tried defining MAX_K as a double inside the program with the same results. I don't understand why the program is not exiting since clearly 1000000000000000001 > 1000000000000000000.
Here's my code:

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

#define MAX_K 1000000000000000000

int main(int argc, char *argv[]) {

//  double MAX_K = 1000000000000000000; 

  double K;

  if (argc != 2) {
    exit(1);
  }

  K = strtod(argv[1], NULL);

  if (K > MAX_K) {
    exit(1);
  }

  printf("OK\n");

  return 0;
}
Urler
  • 500
  • 3
  • 8
  • 23

1 Answers1

2

strtod() returns the closest double representable by the input string.

Inputs such as "1000000000000000000" and "1000000000000000001" will both typically convert to the same double given the finite precision of double.

So although "1000000000000000001" was entered, K took on a value of 1000000000000000000 and did not fail the limit test.

This is a precision issue, not a range issue. With double values like "10000 (total 300 zeros) 000" can be entered and strtod() will covert to the nearest double that will be as expected in the first 15 ** decimal digits.

** Per spec, DBL_DIG is at least 10

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • is there a way to read in a huge number such as 10^18 without it being converted to a closest double so the check would pass? – Urler Sep 25 '14 at 16:04
  • @Stochastic13 Yes, 2 options: use type `long long`, but then you re limited to integers. Your system may support `long double` with even greater range/precision. – chux - Reinstate Monica Sep 25 '14 at 16:06
  • Without resorting to `long double`, a pedantic approach would check if `K > MAX_K`, which is certainly a failure and do extra processing when `K == MAX_K` as the input _may_ be a failure as with "1000000000000000000.0000000001", etc. Should OP provide more details of acceptable/non-acceptable values near `MAX_K` and _why_ this is important (the higher level issue), a solution could be had. – chux - Reinstate Monica Sep 25 '14 at 16:26
  • I want to check if 1 <= MAX_K <= 10^18, otherwise the program should fail. I tried changing "doubel K" to "long double K" with no luck. You explained before that stdol converts arg[1] to a closest double so I'm a little confused how changing K to long double would help. I think I misunderstood how this problem could be remedied. – Urler Sep 25 '14 at 16:34
  • @Stochastic13 I think you want to check `1 <= K <= 10^18`, not `MAX_K`. Using `long double k` implies also using `strtold()` instead of `strtod()`. Also better to use `#define MAX_K 1000000000000000000.0` (Add .0). But to the point: If user enters "1000000000000000001" or "1000000000000000000", both will convert to the `double 1000000000000000000.0`. How then does entering "1000000000000000001" fail the _rest_ of the program? IOWs, _why_ does the check need to fail input "1000000000000000001"? – chux - Reinstate Monica Sep 25 '14 at 16:47
  • @Stochastic13 Are only integer values allowed for `K`? If so, convert to a `long long` and test against `#define MAX_K 1000000000000000000`. – chux - Reinstate Monica Sep 25 '14 at 16:51
  • 1
    Thank you, I converted K to long double and used strtold(), and the check passed. – Urler Sep 25 '14 at 16:57