I am currently implementing a Fraction class for training my OOP skills, and I have got to a problem... In my class, you are able to do math operations between:
Fraction & Fraction
Integer & Fraction
Fraction & Integer
And I want to add both:
Fraction & Float
Float & Fraction
Since when I work with integers, what I do is to make them a Fraction with denominator 1, I want to, when operating with float, creating a Fraction that represents that given float. And that is where I have my problem.
Firstly, the minimum code required to understand my Fraction class:
class Fraction(object):
def __init__(self,num,den=1,reduce=True):
# only accept integers or convertable strings
if not(type(num) == int and type(den) == int):
if type(num) == str:
try:
num = int(num)
except ValueError:
raise RuntimeError("You can only pass to the numerator and \
denominator integers or integer convertable strings!")
else:
raise RuntimeError("You can only pass to the numerator and \
denominator integers or integer convertable strings!")
if type(den) == str:
try:
den = int(den)
except ValueError:
raise RuntimeError("You can only pass to the numerator and \
denominator integers or integer convertable strings!")
else:
raise RuntimeError("You can only pass to the numerator and \
denominator integers or integer convertable strings!")
# don't accept fractions with denominator 0
if den == 0:
raise ZeroDivisionError("The denominator must not be 0")
# if both num and den are negative, flip both
if num < 0 and den < 0:
num = abs(num)
den = abs(num)
# if only the den is negative, change the "-" to the numerator
elif den < 0:
num *= -1
den = abs(den)
self.num = num
self.den = den
# the self.auto is a variable that will tell us if we are supposed to
#automatically reduce the Fraction to its lower terms. when doing some
#maths, if either one of the fractions has self.auto==False, the result
#will also have self.auto==False
self.auto = reduce
if self.auto:
self.reduce()
def float_to_fraction(f):
'''should not be called by an instance of a Fraction, since it does not\
accept, purposedly, the "self" argument. Instead, call it as\
Fraction.float_to_fraction to create a new Fraction with a given float'''
# Start by making the number a string
f = str(f)
exp = ""
# If the number has an exponent (is multiplied by 10 to the power of sth
#store it for later.
if "e" in f:
# Get the "e+N" or "e-N"
exp = f[f.index("e"):]
# Slice the exponent from the string
f = f[:f.index("e")]
# Start the numerator and the denominator
num = "0"
den = "1"
# Variable to check if we passed a ".", marking the decimal part of a
#number
decimal = False
for char in f:
if char != ".":
# Add the current char to the numerator
num += char
if decimal:
# If we are to the right of the ".", also add a 0 to the
#denominator to keep proportion
den += "0"
# Slice parsed character
f = f[1:]
if char == ".":
# Tell the function we are now going to the decimal part of the
#float.
decimal = True
# Slice the "."
f = f[1:]
# Parse the exponent, if there is one
if exp != "":
# If it is a negative exponent, we should make the denominator bigger
if exp[1] == "-":
# Add as many 0s to the den as the absolute value of what is to
#the right of the "-" sign. e.g.: if exp = "e-12", add 12 zeros
den += "0"*int(exp[2:])
# Same stuff as above, but in the numerator
if exp[1] == "+":
num += "0"*int(exp[2:])
# Last, return the Fraction object with the parsed num and den!
return Fraction(int(num),int(den))
My float_to_fraction() function converts, 100% accurately, a given float to a Fraction. But as I remember from my math classes a cyclic decimal with a n-digit long cycle, like 0.123123123123... or 0.(123) can be written in the form of a fraction with numerator = cycle and denominator = (as many 9s as the length of the cycle):
123/999 = 0.(123)
3/9 (=1/3) = 0.(3); 142857/999999 (=1/7) = 0.(142857) etc, etc...
But with this implementation, if I pass to the float_to_fraction() an argument like 1/3, it will parse "0.3333333333333333" which is finite, returning this Fraction: 3333333333333333/10000000000000000. It IS accurate, since I passed to the function a finite number! How can I implement, in this function, a way of recognizing cyclic decimals, so I can return, instead of a Fraction with a denominator = 10^n, a denominator with loads of 9s.
The best way to convert a decimal expression into an approximating rational is via the continued fraction expansion.
For x=0.123123123123 this results in
r=x,
a[0]=floor(r)=0, r=r-a[0], r=1/r=8.121951219520,
a[1]=floor(r)=8, r=r-a[1], r=1/r=8.199999999453,
a[2]=floor(r)=8, r=r-a[2], r=1/r=5.000000013653,
a[3]=floor(r)=5, r=r-a[3], r=1/r=73243975.48780,
And at this point r-a[3]<1e-5 the iteration stops. The rational approximation found is
x=1/(8+1/(8+1/5))=1/(8+5/41)=41/333 (=123/999)
The intermediate convergents are
1/8=0.125, x- 1/8 = -0.001876876877,
1/(8+1/8)=8/65, x- 8/65 = 0.0000462000460,
41/333, x-41/333 = -1.231231231231e-13.
Related
I am trying to convert positive and negative fractions to binary, I found the following approach online (https://www.geeksforgeeks.org/convert-decimal-fraction-binary-number/) to convert positive fractions to binary and tried to extend it to support the negative fractions.
I am trying to do the 2's complement on the fractional part. Any help is much appreciated.
# decimal to binary number
# Function to convert decimal to binary
# upto k-precision after decimal point
def decimalToBinary(num, k_prec) :
binary = ""
# Fetch the integral part of
# decimal number
Integral = int(num)
# Fetch the fractional part
# decimal number
fractional = num - Integral
# Conversion of integral part to
# binary equivalent
while (Integral) :
rem = Integral % 2
# Append 0 in binary
binary += str(rem);
Integral //= 2
# Reverse string to get original
# binary equivalent
binary = binary[ : : -1]
# Append point before conversion
# of fractional part
binary += '.'
# Conversion of fractional part
# to binary equivalent
while (k_prec) :
# Find next bit in fraction
fractional *= 2
fract_bit = int(fractional)
if (fract_bit == 1) :
fractional -= fract_bit
binary += '1'
else :
binary += '0'
k_prec -= 1
if (num < 0): # if negative numbers do the two's complement
binary = ~binary # struck here.
else:
binary = binary
return binary
# Driver code
if __name__ == "__main__" :
num_list=[1, 0, 0.924, -0.383]
for i in num_list:
print(i, decimalToBinary(i,8))
macky#test:~/test$ python frac_to_binary.py
(1, '1.00000000')
(0, '.00000000')
(0.924, '.11101100')
Traceback (most recent call last):
File "frac_to_binary.py", line 63, in <module>
print(i, decimalToBinary(i,8))
File "frac_to_binary.py", line 54, in decimalToBinary
binary = ~binary
TypeError: bad operand type for unary ~: 'str'
There are actually a few ways to display binary numbers as negatives. The important thing to remember is to watch your bit size; set your bit size larger than the max value that you want to convert, or weird things may happen:
bits = 4 for numbers <= 7 (0111)
bits = 5 for numbers <= 15 (01111)
bits = 8 for numbers <= 127 (01111111)
Another thing to remember is that you have to convert the whole binary representation, not each part.
I modified your function to display four types of representations: Signed, Sign Magnitude, One's Complement, and Two's Complement:
NOTE - Tested on CentOS 7.9, using Python 2.7, and on Ubuntu 20.04, using Python 3.8
"""Program to convert rational numbers to signed and unsigned binary representations
Signed: Add a sign (0001 = 1, -0001 = -1)
Sign Magnitude: The sign is the most significant bit (0001 = 1, 1001 = -1)
One's Complement: Flip all the bits to their opposite value (0001 = 1, 1110 = -1)
Two's Complement: Flip all the bits, then add 1 to the least significant bit (0001 = 1, 1111 = -1)
Signed and decimal values checked at
https://www.rapidtables.com/convert/number/binary-to-decimal.html
Complements checked at https://planetcalc.com/747/
Warning: Set your bit size larger than the max value that you want to convert:
bits = 4 for numbers <= 7 (0111)
bits = 5 for numbers <= 15 (01111)
...
bits = 8 for numbers <= 127 (01111111)
"""
def decimal_to_binary(num, bits):
"""Function to convert rational numbers to binary representations
:param float num: The decimal to convert to binary
:param int bits: The bit size; see warning in the module docstring
:return: A formatted string with Signed, Sign Mag, One's Comp, and Two's Comp representations
:rtype: str
"""
# Ensure the number is a float
num *= 1.0
# Separate the number's components
whole_part = int(str(num).split(".")[0])
decimal_part = float("." + str(num).split(".")[1])
# Convert the whole part to binary
if whole_part >= 0:
whole_binary = format(whole_part, "0{0}b".format(bits))
else:
# Remove the sign
whole_binary = format(whole_part * -1, "0{0}b".format(bits))
# Convert the decimal part to binary
k_prec = bits
if decimal_part == 0:
decimal_binary = format(0, "0{0}b".format(k_prec))
else:
db_list = []
while k_prec > 0:
decimal_part *= 2
db_list.append(int(decimal_part))
decimal_part -= int(decimal_part)
k_prec -= 1
decimal_binary = ''.join(str(d) for d in db_list)
# Put the binary representations back together and sign (for Signed and Sign Magnitude)
binary = whole_binary + "." + decimal_binary
mag_binary = "0" + binary[1:] if num >= 0 else "1" + binary[1:]
signed_binary = binary if num >= 0 else "-" + binary
if num >= 0:
ones_binary = "n/a"
twos_binary = ""
else:
# Create an unsigned binary representation (for Complements)
raw_binary = whole_binary + decimal_binary
ones_binary = ""
# Flip bits; as chepner says, ~ doesn't work on strings
for c in raw_binary:
ones_binary += '1' if c == '0' else '0'
# Add 1 to the least significant digit
twos_binary = bin(int(ones_binary, 2) + 1)
# Format for display
ones_binary = ones_binary.replace("0b", "")
ones_binary = ones_binary[:bits] + "." + ones_binary[bits:]
twos_binary = twos_binary.replace("0b", "")
twos_binary = twos_binary[:bits] + "." + twos_binary[bits:]
return "{0:>8}\t{1:>10}\t{2}\t{3}\t{4}".format(
num, signed_binary, mag_binary, ones_binary, twos_binary)
def main():
# I am using 4 bits for readability, so I am keeping the numbers below 7
num_list = [1, 0, 0.924, -0.383, -0.5, -1, ]
print("Original\t Signed\t Sign Mag\tOne's Comp\tTwo's Comp")
for i in num_list:
print(decimal_to_binary(i, 4))
if __name__ == "__main__":
main()
Output:
Original Signed Sign Mag One's Comp Two's Comp
1.0 0001.0000 0001.0000 n/a
0.0 0000.0000 0000.0000 n/a
0.924 0000.1110 0000.1110 n/a
-0.383 -0000.0110 1000.0110 1111.1001 1111.1010
-0.5 -0000.1000 1000.1000 1111.0111 1111.1000
-1.0 -0001.0000 1001.0000 1110.1111 1111.0000
I tested the results using RapidTables' Binary to Decimal converter and PlanetCalc's One's complement, and two's complement binary codes calculator.
If I had more time, I would break this up into separate functions and streamline a few things, but I leave that up to you. Good luck with your code!
fraction.Fraction.limit_denominator exists, and finds the closest fraction that has a denominator smaller than a given maximum. But there is no obvious way to limit the numerator.
What is the best way to also limit the numerator? (I.e. to find the closest fraction that has both numerator and denominator smaller than a given maximum.)
(Goal: I need to limit the numerator also to 2**32, because TIFF files store fractions as two unsigned 32-bit integers.)
A crude approach (that probably does not find the truly closest fraction):
from fractions import Fraction
def limit_32bit_rational(f: float) -> Fraction:
ndigits = 15
while True:
r = Fraction.from_float(f).limit_denominator(1000000)
if r.numerator < 2**32:
return r
f = round(f, ndigits)
ndigits -= 1
Is there a better way to find the closest fraction that has nominator and denominator less than 2**32?
You can use the float.as_integer_ratio() method to get the numerator and denominator of any float:
f = 2345.245624
numerator, denominator = (f).as_integer_ratio()
print("Numerator", numerator)
Output:
2578624833578781
EDIT:
You can try using an if statement to check if the numerator or denominator is greater than 2 ** 32; if so, multiply each of them by a scale and round them to the nearest whole numbers:
def limit_32bit_rational(f):
numerator, denominator = (f).as_integer_ratio()
max_num = 2 ** 32
if numerator > max_num or denominator > max_num:
scale = max_num / max(numerator, denominator)
return round(numerator * scale), round(denominator * scale)
return numerator, denominator
You could also flip the fraction and call limit_denominator to limit the numerator and flip the result back again:
def limit_32bit_rational(f: float) -> Fraction:
tmp = Fraction(f).limit_denominator(0xFFFF_FFFF)
if tmp.numerator <= 0xFFFF_FFFF:
# makes sure we don't flip if numerator is 0
return tmp
else:
# flip numerator with denominator to limit the inputs numerator
tmp = Fraction(numerator=tmp.denominator, denominator=tmp.numerator).limit_denominator(0xFFFF_FFFF)
return Fraction(numerator=tmp.denominator, denominator=tmp.numerator)
Project Euler Problem 26:
A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:
1/2 = 0.5
1/3 = 0.(3)
1/4 = 0.25
1/5 = 0.2
1/6 = 0.1(6)
1/7 = 0.(142857)
1/8 = 0.125
1/9 = 0.(1)
1/10 = 0.1
Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.
Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.
Although I have already provided the correct answer to the problem (983), I still think that the code could have developed even further as I think the code I wrote could be wrong if the value of d can go over 1000.
I think the code might be wrong because the string limit of the fraction is 20 and what if there is a fraction that has over 20 recurring cycle?
I have tried using format() to increasing the string limit of the fraction, but I realise that the digits after the 20th string are not any of the repeating recurring numbers.
import time
import math
timeStart = time.time()
prime_numbers = []
def is_prime(n):
for i in range(2, int(math.sqrt(n)+1)):
if n % i == 0:
return False
return True
def numbers(n):
for number in range(2, n):
if is_prime(number):
prime_numbers.append(number)
def main():
limit = 1000
longest_recurring_cycle = 0
longest_value = 0
numbers(limit)
for d in prime_numbers:
fraction = str(1/d)
count = 1
if len(fraction) > 15:
for index, recurring_cycle in enumerate(fraction[3:10]):
if recurring_cycle == fraction[2] and recurring_cycle ==
fraction[index + 3 + count]:
break
elif count >= longest_recurring_cycle:
longest_recurring_cycle = count
longest_value = d
count += 1
print(longest_value)
print(time.time() - timeStart, "seconds")
main()
tltr I want to find a way to increase the string limit of the fraction that produces the right number.
I would recommend simulating long division. That is, the digits of 1/7 are 10//7=1, remainder is 10 - 1*7 = 3. Next decimal is 30//7 = 4. Remainder is 2. And so on, until the remainder is equal to 1 again. Then count the length of the cycle.
def cycle(denom,num=1):
digit = None
decimals=[]
while digit not in decimals:
decimals += [digit]
digit = num * 10 // denom
remainder = num * 10 - digit * denom
num = remainder
print(digit)
return len(decimals) - decimals.index(digit)
cycle(3)
Here is my code and i got the answer with in a second.I used the simple long division method and considered only remainders.Note that this code doesn't valid when the numerator isn't equal to one.When it is,the function should be develop.
def count_repeat(number):
_list = [10]
while ((_list[-1]) % number)*10 not in _list:
_list.append((_list[-1] % number)*10)
return len(_list)-_list.index((_list[-1] % number)*10)
repeat_lenth = 0
relevent_i = 2
for i in range(2, 1000):
if count_repeat(i) >= repeat_lenth:
repeat_lenth = count_repeat(i)
relevent_i = i
print(f"{i}-{repeat_lenth}")
print(relevent_i)
def repeating_cycle(denom :int, num :int=1)->int:
'''We will do long division method but we will be tracking the reminder throught the division
The reason for doing it is sometime the the number in quotient might repeat even though it is part of
full cycle. e.g. 1/17 = 0.(0588235294117647) if we were to only look at quotient then 8 is repeted just at the 4th place but our
actual cycle is of 16 digits.And this is very well known in maths'''
reminders = []
rems = None
while rems not in reminders:
reminders.append(rems)
num *= 10
rems = num % denom
# reminders.append(rems)
reminders.pop(0)
return len(reminders)
Well I show someone's answer and that person was keeping track of digits in quotient which might not always get the answer e.g. 1/17 = 0.(058823...) and we see the third 8 is directly repeated but the cycle does not repeat there, infact it repeats after 16 digits, and I that is why it is better to keep track of reminders instead of digits in quotient.
Today I wrote a naive function that converts a float to a string by repeatedly modding by 10 and dividing by 10.
def to_string(x):
r = ""
while x >= 1.0:
r = str(int(x%10)) + r
x /= 10.0
return r
I then tested my function against Python's built-in capability to convert a float to a string. Not too surprisingly, my function differs on large numbers.
>>> to_string(1e30)
'1000000000000000424684240284426'
>>> "%.f"%1e30
'1000000000000000019884624838656'
So, my question is: what computation do I have to do to get the digits that Python gets?
Here is a very simple solution. It is not intended to be efficient or to handle any values other than positive integers.
#!/usr/bin/python
import math
# This code represents a hexadecimal number using a list in which each item
# is a single hexadecimal digit (an integer from 0 to 15).
# Divide the base-16 digit-list in x by digit d. This uses grade-school
# division, for a single-digit divisor. It returns the quotient in a new
# digit-list and the remainder as a plain integer.
def Divide(x, d):
# If the first digit is smaller than d, start an empty quotient with
# a remainder being carried.
if x[0] < d:
q = []
r = x[0]
# Otherwise, start the quotient by dividing the first digit by d.
else:
q = [x[0] / d]
r = x[0] % d
# For the remaining digits, multiply the remainder by the base and
# add the new digit. Then divide by d, calculating a new digit of the
# quotient and a new remainder to carry.
for i in x[1:]:
r = r*16 + i
q.append(r/d)
r = r % d
return (q, r)
# Convert a positive integer floating-point value to decimal and print it.
def to_string(x):
# Convert input to base 16. This has no rounding errors since the
# floating-point format uses base two, and 16 is a power of two.
t= []
while 0 < x:
# Use remainder modulo 16 to calculate the next digit, then insert it.
t.insert(0, int(x % 16))
# Remove the digit from x.
x = math.floor(x/16)
# Start an empty output string.
output = ""
# Divide the number by 10 until it is zero (is an empty digit list).
# Each time we divide, the remainder is a new digit of the answer.
while t != []:
(t, r) = Divide(t, 10)
output = str(r) + output
print output
to_string(1e30)
I'm trying to convert a floating point number to binary representation; how can I achieve this?
My goal is, however, not to be limited by 2m so I'm hoping for something that could be easily extended to any base (3, 4, 8) ecc.
I've got a straightforward implementation so far for integers:
import string
LETTER = '0123456789' + string.ascii_lowercase
def convert_int(num, base):
if base == 1:
print "WARNING! ASKING FOR BASE = 1"
return '1' * num if num != 0 else '0'
if base > 36: raise ValueError('base must be >= 1 and <= 36')
num, rest = divmod(num, base)
rest = [LETTER[rest]]
while num >= base:
num, r = divmod(num, base)
rest.append(LETTER[r])
rest.reverse()
return (LETTER[num] if num else '') + ''.join(str(x) for x in rest)
any help appreciated :)
edit:
def convert_float(num, base, digits=None):
num = float(num)
if digits is None: digits = 6
num = int(round(num * pow(base, digits)))
num = convert_int(num, base)
num = num[:-digits] + '.' + num[:digits]
if num.startswith('.'): num = '0' + num
return num
is that right? why do i get this behaviour?
>>> convert_float(1289.2893, 16)
'509.5094a0'
>>> float.hex(1289.2983)
'0x1.42531758e2196p+10'
p.s.
How to convert float number to Binary?
I've read that discussion, but I don't get the answer.. I mean, does it work only for 0.25, 0.125? and I dont understand the phrase 'must be in reverse order'...
For floats there is built-in method hex().
http://docs.python.org/library/stdtypes.html#float.hex
It gives you the hexadecimal representation of a given number. And translation form hex to binary is trivial.
For example:
In [15]: float.hex(1.25)
Out[15]: '0x1.4000000000000p+0'
In [16]: float.hex(8.25)
Out[16]: '0x1.0800000000000p+3'
Next answer with a bit of theory.
Explanation below does not explain IEEE Floating Point standard only general ideas concerning representation of floating point numbers
Every float number is represented as a fractional part multiplied by an exponent multiplied by a sign. Additionally there is so called bias for exponent, which will be explained bellow.
So we have
Sign bit
Fractional part digits
Exponent part digits
Example for base 2 with 8 bit fraction and 8 bit exponent
Bits in fraction part tell us which summands (numbers to be added) from sequence below are to be included in represented number value
2^-1 + 2^-2 + 2^-3 + 2^-4 + 2^-5 + 2^-6 + 2^-7 + 2^-8
So if you have say 01101101 in fractional part it gives
0*2^-1 + 1*2^-2 + 1*2^-3 + 0*2^-4 + 1*2^-5 + 1*2^-6 + 0*2^-7 + 1*2^-8 = 0.42578125
Now non-zero numbers that are representable that way fall between
2 ** -8 = 0.00390625 and 1 - 2**-8 = 0.99609375
Here the exponent part comes in. Exponent allows us to represent very big numbers by multiplying the fraction part by exponent. So if we have an 8bit exponent we can multiply the resulting fraction by numbers between 0 and 2^255.
So going back to example above let's take exponent of 11000011 = 195.
We have fractional part of 01101101 = 0.42578125 and exponent part 11000011 = 195. It gives us the number 0.42578125 * 2^195, this is really big number.
So far we can represent non-zero numbers between 2^-8 * 2^0 and (1-2^-8) * 2^255. This allows for very big numbers but not for very small numbers. In order to be able to represent small numbers we have to include so called bias in our exponent. It is a number that will be always subtracted from exponent in order to allow for representation of small numbers.
Let's take a bias of 127. Now all exponents are subtracted 127. So numbers that can be represented are between 2^-8 * 2^(0 - 127) and (1-2^-8) * 2^(255 - 127 = 128)
Example number is now 0.42578125 * 2^(195-127 = 68) which is still pretty big.
Example ends
In order to understand this better try to experiment with different bases and sizes for fractional and exponential part. At beginning don't try with odd bases because it only complicates things necessary.
Once you grasp how this representation works you should be able to write code to obtain representation of any number in any base, fractional/exponential part combination.
If you want to convert a float to a string with d digits after the decimal radix point:
Multiply the number by base**d.
Round to the nearest integer.
Convert the integer to a string.
Insert the . character d digits before the end.
For example, to represent 0.1 in base 12 with 4 decimal dozenal places,
0.1 × 124 = 2073.6
Round to nearest integer → 2074
Convert to string → 124A
Add radix point → 0.124A
This isn't the same style of binary representation that you want, but this will convert an IEEE 754 into it's sign, mantissa and base, which can be used to create a hex representation in a fairly straightforward fashion. Note that the 'value' of the mantissa is 1+BINARY, where BINARY is the binary representation - hence the -1 in the return.
I wrote this code and am declaring it public domain.
def disect_float(f):
f = float(f); #fixes passing integers
sign = 0x00; #positive
exp = 0;
mant = 0;
if(f < 0): #make f positive, store the sign
sign = '-'; #negative
f = -f;
#get the mantissa by itself
while(f % 1 > 0): #exp is positive
f*=2
exp+=1
#while(f % 1 > 0):
tf = f/2;
while(tf % 1 <= 0): #exp is negative
exp-=1;
f=tf;
tf=f/2;
if(exp < -1024): break;
mant=int(f);
return sign, mant-1, exp;
There is one trick that i observed that we can do using simple string manipulations. I felt this method to be simpler than other methods that i came across.
s = "1101.0101"
s1, s2 = s.split(".")
s1 = int(s1, 2)
s2 = int(s2, 2)/(2**len(s2))
x = s1+s2
print(x)
Output :
13.3125
Hope it will be helpful to someone.
Answering the title directly and using float.hex, which uses 64bit IEE754, one could write this method:
def float_to_bin(x):
if x == 0:
return "0" * 64
w, sign = (float.hex(x), 0) if x > 0 else (float.hex(x)[1:], 1)
mantissa, exp = int(w[4:17], 16), int(w[18:])
return "{}{:011b}{:052b}".format(sign, exp + 1023, mantissa)
float_to_bin(-0.001) # '1011111101010000000010110011111101011000011011100110110100101010'
Note however, this does not work for NaN and Inf.