473,320 Members | 1,820 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Re: Comparing float and decimal

Gerhard Häring wrote:
D'Arcy J.M. Cain wrote:
>I'm not sure I follow this logic. Can someone explain why float and
integer can be compared with each other and decimal can be compared to
integer but decimal can't be compared to float?
>>>>from decimal import Decimal
i = 10
f = 10.0
d = Decimal("10.00")
i == f
True
>>>>i == d
True
>>>>f == d
False

I can give you the technical answer after reading the sources of the
decimal module: you can only compare to Decimal what can be converted to
Decimal. And that is int, long and another Decimal.
The new fractions module acts differently, which is to say, as most
would want.
>>from fractions import Fraction as F
F(1) == 1.0
True
>>F(1.0)
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
F(1.0)
File "C:\Program Files\Python30\lib\fractions.py", line 97, in __new__
numerator = operator.index(numerator)
TypeError: 'float' object cannot be interpreted as an integer
>>F(1,2) == .5
True
>>.5 == F(1,2)
True

so Fraction obviously does comparisons differently.

Decimal is something of an anomaly in Python because it was written to
exactly follow an external standard, with no concessions to what would
be sensible for Python. It is possible that that standard mandates that
Decimals not compare to floats.

tjr

Sep 23 '08 #1
6 3646
Terry Reedy <tj*****@udel.eduwrote:
The new fractions module acts differently, which is to say, as most
would want.
>>from fractions import Fraction as F
>>F(1) == 1.0
True
>>F(1.0)
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
F(1.0)
File "C:\Program Files\Python30\lib\fractions.py", line 97, in __new__
numerator = operator.index(numerator)
TypeError: 'float' object cannot be interpreted as an integer
Both the Fraction module and the Decimal module could represent floats
exactly and reversibly since floats are of the form

mantissa * 2**exponent

which is exactly representable as a fraction (rational) and also as

mantissa2 * 10**exponent2

as to why we don't do this...

I guess it is to preserve the sanity of the user when they write
fraction(0.1) or decimal(0.1) did they really mean fraction(1,10),
decimal("0.1") or the exact representations which are
decimal("0.100000000000000005551115123125782702118 1583404541015625")
and fraction(3602879701896397,2**55)

Given that we let the exact representations leak out anyway (which
causes a lot of FAQs in this list), eg
>>0.1
0.10000000000000001

IMHO We should put the exact conversions in for floats to Decimal and
Fraction by default and add a new section to the FAQ!

In that way people will see floats for what they really are - a crude
approximation to a rational number ;-)

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Sep 24 '08 #2
On Sep 23, 7:31*pm, Terry Reedy <tjre...@udel.eduwrote:
Decimal is something of an anomaly in Python because it was written to
exactly follow an external standard, with no concessions to what would
be sensible for Python. *It is possible that that standard mandates that
Decimals not compare to floats.
I don't think the standard says anything about interactions between
Decimals and floats. But there's certainly been a feeling amongst at
least some of the developers that the job of Python's decimal module
is
to implement the standard and no more, and that extensions to its
functionality belong elsewhere.

Regarding equality, there's at least one technical issue: the
requirement
that objects that compare equal hash equal. How do you come up with
efficient hash operations for integers, floats, Decimals and Fractions
that satisfy this requirement?

For other arithmetic operations: should the sum of a float and a
Decimal
produce a Decimal or a float? Why? It's not at all clear to me that
either of these types is 'higher up' the numerical tower than the
other.

Mark
Sep 24 '08 #3
Mark Dickinson wrote:
On Sep 23, 7:31 pm, Terry Reedy <tjre...@udel.eduwrote:
>Decimal is something of an anomaly in Python because it was written to
exactly follow an external standard, with no concessions to what would
be sensible for Python. It is possible that that standard mandates that
Decimals not compare to floats.

I don't think the standard says anything about interactions between
Decimals and floats.
If there is not now, there could be in the future, and the decimal
authors are committed to follow the standard wherever it goes.
Therefore, the safe course, to avoid possible future deprecations due to
doing too much, is to only do what is mandated.
But there's certainly been a feeling amongst at
least some of the developers that the job of Python's decimal module
is to implement the standard and no more, and that extensions to its
functionality belong elsewhere.
For the reason just stated. A slightly different take is this. The
reason for following the standard is so that decimal code in Python is
exact interconversion both from and to decimal code in other languages.
(And one reason for *that* is that one purpose of the standard is to
reliably implement legal and contractual standards for financial
calculations.) Using extensions in Python could break/deprecate code
translated away from Python.
Regarding equality, there's at least one technical issue: the
requirement
that objects that compare equal hash equal. How do you come up with
efficient hash operations for integers, floats, Decimals and Fractions
that satisfy this requirement?
For integral values, this is no problem.
>>hash(1) == hash(1.0) == hash(decimal.Decimal(1)) ==
hash(fractions.Fraction(1)) == 1
True
For other arithmetic operations: should the sum of a float and a
Decimal produce a Decimal or a float? Why? It's not at all clear to me that
either of these types is 'higher up' the numerical tower than the
other.
Floats and fractions have the same issue. Fractions are converted to
floats. I can think of two reasons: float operations are faster; floats
are my typically thought of as inexact and since the result is likely to
be inexact (rounded), float is the more appropriate type to express
that. Anyone who disagrees with the choice for their application can
explicitly convert the float to a fraction.

Decimals can also be converted to floats (they also have a __float__
method). But unlike fractions, the conversion must be explicit, using
float(decimal), instead of implicit, as with ints and fractions.

Someone *could* write a PyDecimal wrapper that would do implicit
conversion and thereby more completely integrate decimals with other
Python numbers, but I doubt that saving transitivity of equality will be
sufficient motivation ;-).

Terry Jan Reedy

Sep 24 '08 #4
On Wed, 24 Sep 2008 04:30:03 -0500, Nick Craig-Wood wrote:

Both the Fraction module and the Decimal module could represent floats
exactly and reversibly since floats are of the form

mantissa * 2**exponent

which is exactly representable as a fraction (rational) and also as

mantissa2 * 10**exponent2

as to why we don't do this...

I guess it is to preserve the sanity of the user when they write
fraction(0.1) or decimal(0.1) did they really mean fraction(1,10),
decimal("0.1") or the exact representations which are
decimal("0.100000000000000005551115123125782702118 1583404541015625") and
fraction(3602879701896397,2**55)

I would say that in practice the chances that somebody *actually* wanted
0.100000000000000005551115123125782702118158340454 1015625 when they wrote
0.1 is about the same as the chances that the BDFL will support braces in
Python 3.0.

(Hint: "from __future__ import braces")

Given that we let the exact representations leak out anyway (which
causes a lot of FAQs in this list), eg
>>>0.1
0.10000000000000001

IMHO We should put the exact conversions in for floats to Decimal and
Fraction by default and add a new section to the FAQ!

But of the reasons for having the Decimal module is to avoid such leaky
abstractions. Without Decimal (or fraction) there's no obvious way to get
0.1 exactly. It seems perverse to suggest that by default Decimal should
deliberately expose the same leaky abstraction that causes so much
trouble when people use floats.
In that way people will see floats for what they really are - a crude
approximation to a rational number ;-)
You can already see that just by printing a float:
>>0.3
0.29999999999999999
>>0.1
0.10000000000000001
--
Steven
Sep 25 '08 #5
On Sep 24, 6:18*pm, Terry Reedy <tjre...@udel.eduwrote:
If there is not now, there could be in the future, and the decimal
authors are committed to follow the standard wherever it goes.
Therefore, the safe course, to avoid possible future deprecations due to
doing too much, is to only do what is mandated.
Makes sense. It looks as though the standard's pretty stable now
though; I'd be quite surprised to see it evolve to include discussion
of floats. But then again, people thought it was stable just before
all the extra transcendental operations appeared. :-)
For integral values, this is no problem.
*>>hash(1) == hash(1.0) == hash(decimal.Decimal(1)) ==
hash(fractions.Fraction(1)) == 1
True
Getting integers and Decimals to hash equal was actually
something of a pain, and required changing the way that
the hash of a long was computed. The problem in a nutshell:
what's the hash of Decimal('1e100000000')? The number is
clearly an integer, so its hash should be the same as that
of 10**100000000. But computing 10**100000000, and then
finding its hash, is terribly slow... (Try
hash(Decimal('1e100000000')) in Python 2.5 and see
what happens! It's fixed in Python 2.6.)

As more numeric types get added to Python, this
'equal implies equal hash' requirement becomes more
and more untenable, and difficult to maintain. I also find
it a rather unnatural requirement: numeric equality
is, to me, a weaker equivalence relation than the one
that should be used for identifying keys in dictionaries,
elements of sets, etc. Fraction(1, 2) and 0.5 should, to my
eyes, be considered
different elements of a set. But the only way to 'fix' this
would be to have Python recognise two different types of
equality, and then it wouldn't be Python any more.

The SAGE folks also discovered that they couldn't
maintain the hash requirement.
Decimals can also be converted to floats (they also have a *__float__
method). *But unlike fractions, the conversion must be explicit, using
float(decimal), instead of implicit, as with ints and fractions.
Maybe: if I *had* to pick a direction, I'd make float + Decimal
produce a Decimal, on the basis that Decimal is arbitrary precision
and that the float->Decimal conversion can be made losslessly.
But then there are a whole host of decisions one has to make
about rounding, significant zeros, ... (And then, as you point
out, Cowlishaw might come out with a new version of the standard
that does include interactions with floats, and makes an entirely
different set of decisions...)

Mark
Sep 25 '08 #6
Mark Dickinson wrote:
On Sep 24, 6:18 pm, Terry Reedy <tjre...@udel.eduwrote:
>If there is not now, there could be in the future, and the decimal
authors are committed to follow the standard wherever it goes.
Therefore, the safe course, to avoid possible future deprecations due to
doing too much, is to only do what is mandated.

Makes sense. It looks as though the standard's pretty stable now
though; I'd be quite surprised to see it evolve to include discussion
of floats. But then again, people thought it was stable just before
all the extra transcendental operations appeared. :-)
What got me were the bizarre new 'logical' operations whose addition
were rather nonsensical from a Python viewpoint (though probably
sensible from an IBM profit business viewpoint). With those added, and
with this thread, I have decided that Decimals best be thought of as a
separate universe, not to be mixed with other numbers unless one has
good reason to and understands the possible anomalies of doing so. For
pure finance apps, I would think that there should be little reason to mix.

tjr

Sep 26 '08 #7

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

Similar topics

0
by: Robert Oschler | last post by:
Is there a way to use CAST() to convert a string MySQL field to a 'float' value? I know I can convert a string to a SIGNED or UNSIGNED integer value, but not float. I tried FLOAT, DECIMAL, and a...
687
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...
15
by: Kay Schluehr | last post by:
I wonder why this expression works: >>> decimal.Decimal("5.5")**1024 Decimal("1.353299876254915295189966576E+758") but this one causes an error 5.5**1024 Traceback (most recent call...
2
by: O.B. | last post by:
In the following piece of code, the == operator is saying that the two different float values are the same. What's going on here? float testValueA = float.MaxValue; float testValueB =...
18
by: Carramba | last post by:
Hi! is there a better/faster way to compare mantissas of to real number then in following code? #include <stdio.h> #include <stdlib.h> int main(void) { float a,b; int test;
1
Shashi Sadasivan
by: Shashi Sadasivan | last post by:
hi, im comparing two decimal variables d1,d2. at some points, d1 == d2 (where d1 and d2 = 8 shown in debug mode) turns out as false!!! is this a c/c++ version of comparing floats? any ideas on...
7
by: Guido van Brakel | last post by:
Hello I have this now: It now gives a int, but i would like to see floats. How can integrate that into the function? Regards,
17
by: D'Arcy J.M. Cain | last post by:
I'm not sure I follow this logic. Can someone explain why float and integer can be compared with each other and decimal can be compared to integer but decimal can't be compared to float? True...
0
by: =?ISO-8859-1?Q?Gerhard_H=E4ring?= | last post by:
D'Arcy J.M. Cain wrote: I can give you the technical answer after reading the sources of the decimal module: you can only compare to Decimal what can be converted to Decimal. And that is int,...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

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.