Finding next largest/smallest floating point value

P

Peter Ammon

I have a floating point number. I'd like to get the nearest floating
point number that is larger or smaller than the given number. I
investigated FLT_EPSILON but it only seems to be useful if the given
number is 1. Any suggestions?

Thanks,
-Peter
 
T

Thomas Stegen

Peter said:
I have a floating point number. I'd like to get the nearest floating
point number that is larger or smaller than the given number. I
investigated FLT_EPSILON but it only seems to be useful if the given
number is 1. Any suggestions?

You have to scale epsilon to find the number that results when
you change the least significant bit for any given floating point
number. This is quite complicated IIRC, especially when the
exponent changes.

The following link might cover it. I don't know, haven't read it
yet, but it seems to be very good so I am including it even if#
it is not relevant to your question.

http://docs.sun.com/source/806-3568/ncg_goldberg.html
 
R

Rufus V. Smith

I'm sure there's a better way, but:

float num, nextnum,guess;

// can't just add 1.0, because 1.0 could be less than a sig. bit
// play with + or -

guess = num+num;
do {
nextnum = guess;
guess = (num + nextnum) / 2.0;
}
while ((guess != num) && (guess != nextnum)); // could round down or up
 
C

CBFalconer

Peter said:
I have a floating point number. I'd like to get the nearest
floating point number that is larger or smaller than the given
number. I investigated FLT_EPSILON but it only seems to be
useful if the given number is 1. Any suggestions?

#include <float.h>

float scaledepsilon(float number)
{
float trial;

trial = number * FLT_EPSILON;
while (number != (number - trial/2.0) trial = number/2.0;
return trial;
} /* untested, but should be close */

Probably highly suspicious for very small values of number.
 
A

Arin Chaudhuri

Peter said:
I have a floating point number. I'd like to get the nearest floating
point number that is larger or smaller than the given number. I
investigated FLT_EPSILON but it only seems to be useful if the given
number is 1. Any suggestions?

Thanks,
-Peter

If you have a C99 compiler you can use the nextafter functions in math.h

7.12.11.3 The nextafter functions

double nextafter(double x, double y);
float nextafterf(float x, float y);
long double nextafterl(long double x, long double y);

Description
The nextafter functions determine the next representable value, in the
type of the function, after x in the direction of y, where x and y are
first converted to the type of the function. The nextafter functions
return y if x equals y. A range error may occur if the magnitude of x is
the largest finite value representable in the type and the result is
infinite or not representable in the type.

Returns
The nextafter functions return the next representable value in the
specified format after x in the direction of y.
 
D

Dan Pop

In said:
If you have a C99 compiler you can use the nextafter functions in math.h

Nope, you need an implementation of the C99 standard library for that,
not a C99 compiler.

Dan
 
J

Joe Wright

Peter said:
I have a floating point number. I'd like to get the nearest floating
point number that is larger or smaller than the given number. I
investigated FLT_EPSILON but it only seems to be useful if the given
number is 1. Any suggestions?

Thanks,
-Peter

FLT_EPSILON is the smallest value, when added to 1.0 results in a
value greater than 1.0. If you multiply a float value by 1.0 +
FLT_EPSILON I suppose you'll get its next larger value.
 
A

Arin Chaudhuri

Joe said:
FLT_EPSILON is the smallest value, when added to 1.0 results in a value
greater than 1.0. If you multiply a float value by 1.0 + FLT_EPSILON I
suppose you'll get its next larger value.

I guess the next representable number after x will be
x+FLT_EPSILON, if 1<=x<2,
x+2FLT_EPSILON if 2<=x<4
x+4FLT_EPSILON if 4<=x<8
etc.

The following program does not contradict my conjecture.

#include <stdio.h>
#include <math.h>
#include <float.h>

int
main(void)
{
float x=1.5f,y=100.0f;
if ( (x*(1.f+FLT_EPSILON)) == nextafterf(x,y))
{
printf("equal1\n");
}
else if( x+FLT_EPSILON == nextafterf(x,y) )
{
printf("equal2\n");
}
x=2.f;
if ( x+FLT_EPSILON == nextafterf(x,y))/*x
{
printf("equal1\n");
}
else if( x+(FLT_EPSILON+FLT_EPSILON) == nextafterf(x,y) )
{
printf("equal2\n");
}
return 0;
}
 
A

Arin Chaudhuri

Arin said:
I guess the next representable number after x will be
x+FLT_EPSILON, if 1<=x<2,
x+2FLT_EPSILON if 2<=x<4
x+4FLT_EPSILON if 4<=x<8
etc.

I am assuming FLT_RADIX=2, in general I guess the powers of two should
be replaced by the powers of
FLT_RADIX.
 
J

Joe Wright

Arin said:
I am assuming FLT_RADIX=2, in general I guess the powers of two should
be replaced by the powers of
FLT_RADIX.

And we're talking about C. Do you have anything that compiles in C?
 
J

Joe Wright

Arin said:
I guess the next representable number after x will be
x+FLT_EPSILON, if 1<=x<2,
x+2FLT_EPSILON if 2<=x<4
x+4FLT_EPSILON if 4<=x<8
etc.

The following program does not contradict my conjecture.

#include <stdio.h>
#include <math.h>
#include <float.h>

int
main(void)
{
float x=1.5f,y=100.0f;
if ( (x*(1.f+FLT_EPSILON)) == nextafterf(x,y))
{
printf("equal1\n");
}
else if( x+FLT_EPSILON == nextafterf(x,y) )
{
printf("equal2\n");
}
x=2.f;
if ( x+FLT_EPSILON == nextafterf(x,y))/*x
{
printf("equal1\n");
}
else if( x+(FLT_EPSILON+FLT_EPSILON) == nextafterf(x,y) )
{
printf("equal2\n");
}
return 0;
}

What is nextafterf()? I do see it declared in my math.h in a
non-posix and non-ansi context (djgpp gcc 3.0) but it doesn't seem
to be in my info system.

After removing the /*x you left around, the code did compile but
with the -Wall -ansi switches we see nextafterf not explicitly
declared and the program not 'working'.
 
A

Arin Chaudhuri

Joe said:
Arin Chaudhuri wrote:
Joe Wright wrote:
What is nextafterf()? I do see it declared in my math.h in a non-posix
and non-ansi context (djgpp gcc 3.0) but it doesn't seem to be in my
info system.

After removing the /*x you left around, the code did compile but with
the -Wall -ansi switches we see nextafterf not explicitly declared and
the program not 'working'.

I apologize for the trouble caused by the /*.
nextafterf is a part of the C99 standard library, please have a look at
section 7.12.11.3 of the standard. The prototype of nextafterf should be
defined in math.h, I have copypasted the relevant portion of the
standard at the end of the post.

I reasoned as follows (assuming the radix to be 2) :

If, b = b0.b1 b2 b3 ... bp x 2^{e}

is a positive normalized float value, (b0=1)
then the next normalized value that can be represented can be obtained
by adding
0. 0 0 0 ... 1 x 2^{e}= 1. 0 0 0 ... 2^{e-p} = 2^eFLT_EPSILON
to the above, i.e, we increment the last possible "digit".

Hence, for float values of the form, f x 2^{e} with 1<=f<2 the next
normalized number that can be represented is obtained by adding 2^e
FLT_EPSILON

This will not work when we enter the zone of denormalized numbers, (when
b0 is 0 and e is the smallest value possible).

****
7.12.11.3 The nextafter functions

Synopsis
1 #include <math.h>
double nextafter(double x, double y);
float nextafterf(float x, float y);
long double nextafterl(long double x, long double y);

Description
The nextafter functions determine the next representable value, in the
type of the function, after x in the direction of y, where x and y are
first converted to the type of the function. The nextafter functions
return y if x equals y. A range error may occur if the magnitude of x is
the largest finite value representable in the type and the result is
infinite or not representable in the type.

Returns
The nextafter functions return the next representable value in the
specified format after x in the direction of y.
 
A

Arin Chaudhuri

Arin said:
This will not work when we enter the zone of denormalized numbers, (when
b0 is 0 and e is the smallest value possible).

What I meant here was e takes the value FLT_MIN_EXP, and please correct
me if I am wrong, there might exist implementations which do not have
denormals.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top