473,663 Members | 2,903 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Next floating point number

I'm looking for some way to get the next floating point number after any
particular float.

(Any mathematicians out there: I am aware that there is no "next real
number". But floats are not real numbers, they only have a finite
precision.)

According to the IEEE standard, there should be a routine like next(x,y)
which returns the next float starting from x in the direction of y.

Unless I have missed something, Python doesn't appear to give an interface
to the C library's next float function. I assume that most C floating
point libraries will have such a function.

So I came up with a pure Python implementation, and hoped that somebody
who had experience with numerical programming in Python would comment.

def nextfloat(x, y=None):
"""Return the next floating point number starting at x in the
direction of y. If y is not given, the direction is away from zero.
"""
from operator import add, sub
from math import frexp # Returns a tuple (mantissa, exponent)
x = float(x)
if y is None:
if x < 0.0:
op = sub
else:
op = add
elif y > x:
op = add
elif y < x:
op = sub
else:
raise ValueError("dir ection float is equal to starting float")
# We find the next float by finding the smallest float epsilon which
# is distinguishable from x. We know epsilon will be a power of two,
# because floats are implemented internally in binary.
# We get our initial estimate for epsilon from the floating point
# exponent of x.
epsilon = 2.0**(frexp(x)[1]) # epsilon > abs(x)
lasteps = epsilon # Save a copy of our last epsilon for later use.
while op(x, epsilon) != x:
lasteps = epsilon
epsilon /= 2.0
# When we get here, we've halved epsilon one time too many.
# We can't just double it, because that fails for the case where x is
# zero - epsilon will underflow to zero. So we need to save and use
# the previous iteration of epsilon.
return op(x, lasteps)

Thanks,

--
Steven.

Dec 17 '05 #1
9 3509
Steven D'Aprano wrote:
Unless I have missed something, Python doesn't appear to give an interface
to the C library's next float function. I assume that most C floating
point libraries will have such a function.


http://www.mkssoftware.com/docs/man3/nextafter.3.asp

--
Robert Kern
ro*********@gma il.com

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter

Dec 17 '05 #2
[Steven D'Aprano]
I'm looking for some way to get the next floating point number after any
particular float. .... According to the IEEE standard, there should be a routine like next(x,y)
which returns the next float starting from x in the direction of y.

Unless I have missed something, Python doesn't appear to give an interface
to the C library's next float function. I assume that most C floating
point libraries will have such a function.
While the C99 standard defines such a function (several, actually),
the C89 standard does not, so Python can't rely on one being
available. In general, Python's `math` module exposes only standard
C89 libm functions, plus a few extras it can reliably and portably
build itself on top of those. It does not expose platform-specific
libm functions. You can argue with that policy, but not successfully
unless you take over maintenance of mathmodule.c <0.5 wink>.
So I came up with a pure Python implementation, and hoped that somebody
who had experience with numerical programming in Python would comment.


If you're happy with what you wrote, who needs comments ;-) Here's a
careful, "kinda portable" implementation in C:

http://www.netlib.org/toms/722

If you ignore all the end cases (NaNs, infinities, signaling underflow
and overflow, ...), the heart of it is just adding/subtracting 1
to/from the 64-bit double representation, viewing it as an 8-byte
integer. That works fine for the IEEE-754 float representations (but
does not work for all float representations ).

I've used this simple routine based on that observation, which ignores
all endcases, and only works if both input and result are >= 0:

"""
from struct import pack, unpack

def next(x, direction=+1):
bits = unpack(">Q", pack(">d", x))[0]
return unpack(">d", pack(">Q", bits + direction))[0]
"""

For example,
next(0) # smallest denorm > 0 4.9406564584124 654e-324 next(_, -1) # should really signal underflow 0.0 next(1) 1.0000000000000 002 next(1, -1) 0.9999999999999 9989 next(1e100) 1.0000000000000 002e+100 next(1e100, -1)

9.9999999999999 982e+099
Dec 17 '05 #3
On Sat, 17 Dec 2005 14:23:38 +1100, Steven D'Aprano <st***@REMOVETH IScyber.com.au> wrote:
I'm looking for some way to get the next floating point number after any
particular float.

(Any mathematicians out there: I am aware that there is no "next real
number". But floats are not real numbers, they only have a finite
precision.)

According to the IEEE standard, there should be a routine like next(x,y)
which returns the next float starting from x in the direction of y.

Unless I have missed something, Python doesn't appear to give an interface
to the C library's next float function. I assume that most C floating
point libraries will have such a function.

So I came up with a pure Python implementation, and hoped that somebody
who had experience with numerical programming in Python would comment.

def nextfloat(x, y=None):
"""Return the next floating point number starting at x in the
direction of y. If y is not given, the direction is away from zero.
"""
from operator import add, sub
from math import frexp # Returns a tuple (mantissa, exponent)
x = float(x)
if y is None:
if x < 0.0:
op = sub
else:
op = add
elif y > x:
op = add
elif y < x:
op = sub
else:
raise ValueError("dir ection float is equal to starting float")
# We find the next float by finding the smallest float epsilon which
# is distinguishable from x. We know epsilon will be a power of two,
# because floats are implemented internally in binary.
# We get our initial estimate for epsilon from the floating point
# exponent of x.
epsilon = 2.0**(frexp(x)[1]) # epsilon > abs(x)
lasteps = epsilon # Save a copy of our last epsilon for later use.
while op(x, epsilon) != x:
lasteps = epsilon
epsilon /= 2.0
# When we get here, we've halved epsilon one time too many.
# We can't just double it, because that fails for the case where x is
# zero - epsilon will underflow to zero. So we need to save and use
# the previous iteration of epsilon.
return op(x, lasteps)

I wonder if this won't work (for IEEE 754 double that is)

from math import frexp
def nextf(x, y):
f,e = frexp(x)
if (f==0.5 or f==-0.5) and x>=y: eps = 2.0**-54
else: eps = 2.0**-53
if x<y: return (f+eps)*2.0**e
else: return (f-eps)*2.0**e
Regards,
Bengt Richter
Dec 17 '05 #4
On Sat, 17 Dec 2005 09:26:39 +0000, Bengt Richter wrote:

I wonder if this won't work (for IEEE 754 double that is)

from math import frexp
def nextf(x, y):
f,e = frexp(x)
if (f==0.5 or f==-0.5) and x>=y: eps = 2.0**-54
else: eps = 2.0**-53
if x<y: return (f+eps)*2.0**e
else: return (f-eps)*2.0**e


Doesn't that assume floats are 64 bits? Is it possible that they might
not be on some platform or another?

--
Steven.

Dec 17 '05 #5
On Sat, 17 Dec 2005 03:27:11 -0500, Tim Peters wrote:
While the C99 standard defines such a function (several, actually),
the C89 standard does not, so Python can't rely on one being
available. In general, Python's `math` module exposes only standard
C89 libm functions, plus a few extras it can reliably and portably
build itself on top of those. It does not expose platform-specific
libm functions. You can argue with that policy, but not successfully
unless you take over maintenance of mathmodule.c <0.5 wink>.
*rueful smile*

So I came up with a pure Python implementation, and hoped that somebody
who had experience with numerical programming in Python would comment.


If you're happy with what you wrote, who needs comments ;-)


Because I don't know _quite_ enough numeric programming to tell whether my
happiness is justified or just the happiness of somebody who hasn't
noticed the great big enormous bug staring him right in the face :-)

Here's a
careful, "kinda portable" implementation in C:

http://www.netlib.org/toms/722

If you ignore all the end cases (NaNs, infinities, signaling underflow
and overflow, ...), the heart of it is just adding/subtracting 1 to/from
the 64-bit double representation, viewing it as an 8-byte integer. That
works fine for the IEEE-754 float representations (but does not work for
all float representations ).
Will Python always use 64-bit floats?
I've used this simple routine based on that observation, which ignores
all endcases, and only works if both input and result are >= 0:

"""
from struct import pack, unpack

def next(x, direction=+1):
bits = unpack(">Q", pack(">d", x))[0] return unpack(">d", pack(">Q",
bits + direction))[0]
"""


Nice! I played around with struct.pack and unpack using a format string of
"f", but didn't get anywhere, so thanks for this.

--
Steven.

Dec 17 '05 #6
On Sun, 18 Dec 2005 10:27:16 +1100, Steven D'Aprano <st***@REMOVETH IScyber.com.au> wrote:
On Sat, 17 Dec 2005 09:26:39 +0000, Bengt Richter wrote:

I wonder if this won't work (for IEEE 754 double that is) ^^^^^^^^^^^^^^^ ^^^^[1]
from math import frexp
def nextf(x, y):
f,e = frexp(x)
if (f==0.5 or f==-0.5) and x>=y: eps = 2.0**-54
else: eps = 2.0**-53
if x<y: return (f+eps)*2.0**e
else: return (f-eps)*2.0**e


Doesn't that assume floats are 64 bits? Is it possible that they might
not be on some platform or another?

yes [1], and yes ;-)

I wonder if frexp is always available, and if the above would generalize
to something that could be self-tuning via a decorator or conditional defs.
ISTM I recall a FP format based on shifting 4 bits at a time to normalize,
and keeping an exponent as a multiple of 16, which might need a bunch
of epsilons. Obviously too, you wouldn't want to calculate things like 2.**-53
more than once. Also for a limited range of e integers, 2.**e is probably
faster looked up from a precalculated list p2[e]. The math module could
also expose an efficient multiply by a power of two using FSCALE if
the pentium FPU is there. And there's probably other stuff to take advantage
of, like doing it mostly without the FPU, a la Tim's struct thing. Specialized
C code to do the function could be pretty fast.
I'm a little curious what you are using this for.

Regards,
Bengt Richter
Dec 18 '05 #7
On Sun, 18 Dec 2005 08:37:40 +0000, Bengt Richter wrote:
On Sun, 18 Dec 2005 10:27:16 +1100, Steven D'Aprano <st***@REMOVETH IScyber.com.au> wrote:
On Sat, 17 Dec 2005 09:26:39 +0000, Bengt Richter wrote:

I wonder if this won't work (for IEEE 754 double that is)
^^^^^^^^^^^^^^^ ^^^^[1]


Ah! I read that, and blanked it out of my mind :-(

I wonder if frexp is always available,
I believe so, since it is part of the math module.

[snip]
I'm a little curious what you are using this for.


Mostly curiosity -- I'm fascinated by numeric programming, but haven't got
the time to really sit down and learn it properly. But periodically I find
time to dabble for a few hours.

At a more practical level, for many numeric algorithms it is useful to
know the machine accuracy (which of course varies over the range of
floats). The machine accuracy at float x is nextfloat(x) - x. That gives
you an idea of how far apart floats are -- differences smaller than that
number are impossible for the algorithm to resolve.
--
Steven.

Dec 18 '05 #8
[Bengt Richter]
I wonder if frexp is always available,
Yes, `frexp` is a standard C89 libm function. Python's `math` doesn't
contain any platform-specific functions.

....
The math module could also expose an efficient multiply by a power
of two using FSCALE if the pentium FPU is there.


`ldexp` is also a standard C89 libm function, so Python also exposes
that. Whether it uses FSCALE is up to the platform C libm.
Dec 18 '05 #9
[Steven D'Aprano]
...
Will Python always use 64-bit floats?


A CPython "float" is whatever the platform C compiler means by
"double". The C standard doesn't define the size of a double, so
neither does Python define the size of a float.

That said, I don't know of any Python platform to date where a C
double was not 64 bits. It's even possible that all _current_ Python
platforms use exactly the same format for C double.(the IEEE-754
double format), modulo endianness.

There's a subtlety related to that in my pack/unpack code, BTW: using
a ">d" format forces `struct` to use a "standard" big-endian double
encoding, which is 64 bits, regardless of how the platform C stores
doubles and regardless of how many bytes a native C double occupies.
So, oddly enough, the pack/unpack code would work even if the platform
C double used some, e.g., non-IEEE 4-byte VAX float encoding. The
only real docs about this "standard" encoding are in Python's
pickletools module:

"""
float8 = ArgumentDescrip tor(
name='float8',
n=8,
reader=read_flo at8,
doc="""An 8-byte binary representation of a float, big-endian.

The format is unique to Python, and shared with the struct
module (format string '>d') "in theory" (the struct and cPickle
implementations don't share the code -- they should). It's
strongly related to the IEEE-754 double format, and, in normal
cases, is in fact identical to the big-endian 754 double format.
On other boxes the dynamic range is limited to that of a 754
double, and "add a half and chop" rounding is used to reduce
the precision to 53 bits. However, even on a 754 box,
infinities, NaNs, and minus zero may not be handled correctly
(may not survive roundtrip pickling intact).
""")
"""
Dec 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
7842
by: Roger Leigh | last post by:
Hello, I'm writing a fixed-precision floating point class, based on the ideas in the example fixed_pt class in the "Practical C++ Programming" book by Steve Oualline (O' Reilly). This uses a long int to store the value, and the precision (number of decimal points) is variable (it's a templated class): template <size_t _decimal_places = 4> class FixedFloat {
687
23350
by: cody | last post by:
no this is no trollposting and please don't get it wrong but iam very curious why people still use C instead of other languages especially C++. i heard people say C++ is slower than C but i can't believe that. in pieces of the application where speed really matters you can still use "normal" functions or even static methods which is basically the same. in C there arent the simplest things present like constants, each struct and enum...
13
5140
by: Peter Ammon | last post by:
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
13
7778
by: tings | last post by:
An article states: "In floating point maths, where if you divide by a sufficiently large number sufficiently often, you will always be able to reach a value too small to distinguish from zero, given the finite precision you have." What happens when "a value too small to distinguish from zero" is reached by the above division? Underflow? What does it mean "sufficiently often" since only one division should be enough to cause underflow...
15
3923
by: michael.mcgarry | last post by:
Hi, I have a question about floating point precision in C. What is the minimum distinguishable difference between 2 floating point numbers? Does this differ for various computers? Is this the EPSILON? I know in float.h a FLT_EPSILON is defined to be 10^-5. Does this mean that the computer cannot distinguish between 2 numbers that differ by less than this epsilon?
5
3339
by: Peteroid | last post by:
I know how to use rand() to generate random POSITIVE-INTEGER numbers. But, I'd like to generate a random DOUBLE number in the range of 0.0 to 1.0 with resolution of a double (i.e., every possible double value in the range could come up with equal probability). I'd also like to be able to seed this generator (e.g., via the clock) so that the same sequence of random values don't come up every time. Anybody have an easy and fast...
32
4084
by: ma740988 | last post by:
template <class T> inline bool isEqual( const T& a, const T& b, const T epsilon = std::numeric_limits<T>::epsilon() ) { const T diff = a - b; return ( diff <= epsilon ) && ( diff >= -epsilon ); } int main() { std::deque<double> pt ;
2
3121
by: eeyore | last post by:
I've got a problem that seems to be intractable in a purist sense (there are workarounds when you make certain assumptions about the inputs, but no universal solution that I can find). Here's the deal. I've got a floating point variable of any size (float, double, long double, I can make it as big as I like), and the variable contains a monetary value. I need to "round up" this number to the next cent. I'm not "rounding" here, I'm "rounding...
10
3028
by: Steven D'Aprano | last post by:
Is there a simple, elegant way in Python to get the next float from a given one? By "next float", I mean given a float x, I want the smallest float larger than x. Bonus points if I can go in either direction (i.e. the "previous float" as well as the next). Note to maths pedants: I am aware that there is no "next real number", but floats are not reals.
0
8436
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8345
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8858
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8771
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8634
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
5657
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4182
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
2763
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1757
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.