value too big for double

Feb 27, 2010 at 10:49pm
Hi all,
Here's my problem. I'm making an app that draws functions. When I try to draw x*x (or anything else, really) I get a nice parabola in the middle and two ugly vertical lines on both sides. This happens because sometimes x*x is too big for a double. I do not want a larger variable type to store that result. I just want to know a way to tell when x*x will be too big for double so that I can stop drawing the function.
Thank you in advance
Feb 27, 2010 at 11:24pm
You can check x * x against the DOUBLE_MAX macro defined in <climits> (limits.h).

Surely when x * x > DOUBLE_MAX you will get overflow, though? So if DOUBLE_MAX was 8 and x was 3, then x * x would evaluate to 1, because x * x = 3 * 3 = 9, and 9 is 1 more than 8...
Last edited on Feb 27, 2010 at 11:25pm
Feb 28, 2010 at 1:40am
When x > sqrt(DOUBLE_MAX).
Feb 28, 2010 at 11:30am
@chrisname
I can't find DOUBLE_MAX in climits.
There is, however, DBL_MAX in cfloat
That won't work though.
DBL_MAX+1 > DBL_MAX returns 0 for me.
The same happens with INT_MAX.

@Duoas
Yes, but I need a more general solution that would work for any function.
Something more like what chrisname wrote.
Feb 28, 2010 at 12:43pm
There is not any more "general" solution. You need to check your domain before using any function. When you code the function (such as x * x) you can easily prevent range errors by checking against the input domain first.

https://www.securecoding.cert.org/confluence/display/seccode/FLP32-C.+Prevent+or+detect+domain+and+range+errors+in+math+functions

The other option would be to use some sort of implementation-defined trap to catch FPU exceptions (such as overflow, etc).

Sorry.
Feb 28, 2010 at 6:48pm
I think what he means is that
if (x > sqrt(DOUBLE_MAX)
only works for when you're multiplying x by itself.

I can't find DOUBLE_MAX in climits.
There is, however, DBL_MAX in cfloat
That won't work though.
DBL_MAX+1 > DBL_MAX returns 0 for me.
The same happens with INT_MAX.

That'll be because of the overflow. When a variable overflows, it becomes either it's smallest value + the remainder* or 0. I don't know which. I think it's undefined. What you could do is check if the overflow flag is set; but of course you'd have to rewrite that for every processor you wanted to support. On the x86:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* CHECKBIT: returns 1 or 0 if the bit at POS in I is set or not */
#define CHECKBIT(I, POS) (!!((I) & (1 << (POS))))

int main()
{
    /* ... */
    int flags = 0;
    asm("mov %FLAGS, %eax\n":"=a"(flags)); /* gcc/gas syntax */

    if (CHECKBIT(flags, 11)) {
        /* Overflow flag is set */
    } else {
        /* No overflow */
    }
}

but that's obviously a horrendous method. For one thing, it's not portable between toolchains (works only on GNU) and for another, it's not portable between processors, either. I think you'll have to go with Duoas' solution.

*unsigned int i = UINT_MAX + 1;
would make i == 1. I don't know if that works on all processors (if they don't have an overflow flag**, then it wouldn't) or if the result is undefined behaviour.

** http://en.wikipedia.org/wiki/Overflow_flag
Feb 28, 2010 at 7:03pm
Yes, I know I could do this, but I don't think I will..
It would be nice if c++ had some way to check the flags though (throw an exception or something).
I think I'll just leave this project where it is. I'm having other problems with it, so it wouldn't have worked neatly anyway...
Topic archived. No new replies allowed.