digitalmars.D - Comparing double and float values
- Abid H. Mujtaba (15/15) May 12 2011 I am working through "The D Programming Language" by Andrei
- Alexander (6/13) May 12 2011 Quite OK, IMHO:
- Matthew Ong (9/9) May 12 2011 Hi Alexander,
- Jens Mueller (9/21) May 12 2011 That's sounds a bit odd to me. I thought that in application code you
- Matthew Ong (18/18) May 12 2011 Hi jen,
- Alexander (8/12) May 12 2011 The problem is that not every decimal value may be stored with the sam...
- Matthew Ong (9/9) May 12 2011 Hi Alex,
- Don (5/19) May 13 2011 std.math.isIdentical().
- Matthew Ong (15/19) May 16 2011 Hi,
- Abid H. Mujtaba (4/4) May 12 2011 Thanks for the answer. I guess the correct technique would be to
- Andrei Alexandrescu (4/8) May 12 2011 Thanks for considering adding to the errata. Which particular example on...
- Abid H. Mujtaba (20/20) May 12 2011 Section 5.5 Overloading on page 142 it defines the following example
- Andrei Alexandrescu (4/24) May 12 2011 I see. Thanks! I updated the errata with credit:
- Andrei Alexandrescu (3/7) May 12 2011 Also, you may want to peruse the function approxEqual in std.math.
- bearophile (5/6) May 12 2011 I suggest feqrel:
- Abid H. Mujtaba (6/6) May 12 2011 The website defines the signature for feqrel to be:
I am working through "The D Programming Language" by Andrei Alexandrescu and one of the examples compared an array of doubles with an array of floats in a unittest (pg. 143 while discussing function overloading). The unittest failed when I compiled the file using rdmd. I simplified the problem and the following code will not compile: // Code in file test.d unittest { double x = 3.2 ; float y = 3.2 ; assert( x == y ) ; } Running 'rdmd --main -unittest test.d' results in: core.exception.AssertError test(6): unittest failure
May 12 2011
On 12.05.2011 10:03, Abid H. Mujtaba wrote:unittest { double x = 3.2 ; float y = 3.2 ; assert( x == y ) ; }Quite OK, IMHO: x-y = -4.76837e-08 Just regular rounding error, and we are comparing values stored with different precision. Float values quite rarely can store *exact* values. /Alexander
May 12 2011
Hi Alexander, Is there anyway to ensure the comparison of float/double to be done with the raw bits like in Java Double.doubleToRawLongBits(double value) http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Double.html#doubleToRawLongBits%28double%29 when it comes to financial data and percentage computation, that seems to be rather important. Thanks in advance. Matthew Ong
May 12 2011
Matthew Ong wrote:Hi Alexander, Is there anyway to ensure the comparison of float/double to be done with the raw bits like in Java Double.doubleToRawLongBits(double value) http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Double.html#doubleToRawLongBits%28double%29 when it comes to financial data and percentage computation, that seems to be rather important. Thanks in advance.That's sounds a bit odd to me. I thought that in application code you should never compare floating points regarding equality. I only know of something similar in testing code where you compare equality within some number of ulps (unit of least precision). So your use case sounds interesting. Can you elaborate a bit? If you really want to to compare bit by bit it should be possible to cast the floating point values and then perform the comparison. Jens
May 12 2011
Hi jen, If you really want to to compare bit by bit it should be possible to cast the floating point values and then perform the comparison. Please see the URL: http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Double.html#doubleToRawLongBits%28double%29 Casting does that looses the value decimal point value? The most important Returns a representation of the specified floating-point value according to the IEEE 754 floating-point "double format" bit layout, preserving Not-a-Number (NaN) values. underneath the source code, it is just C code: union { double dval; long lval; } They fill dval to get lval and vs. That is important if u use that for searching within a Hashtable like: double[string] myvals; // look for the key string using double?
May 12 2011
On 12.05.2011 12:08, Matthew Ong wrote:Is there anyway to ensure the comparison of float/double to be done with the raw bits like in Java Double.doubleToRawLongBits(double value)The problem is that not every decimal value may be stored with the same bits in float or double, again, due to rounding and other errors. Try it for yourself: http://babbage.cs.qc.edu/IEEE-754/Decimal.html Sure, for simple cases, when no operations are performed and values are simply stored, doubles/floats *may* be sufficient, but anything more important - and errors will accumulate very quickly.when it comes to financial data and percentage computation, that seems to be rather important.When it comes to financial data, where you really need *exact* calculations within given precision, forget about standard floating point formats. Instead, you should use something like http://www.mpfr.org/#intro - with exact and guaranteed precision. Alternatively, you may use something like std.bignum in Phobos with artificial fixed point position (if you need the fast way to go with D). /Alexander
May 12 2011
Hi Alex, Coming from a Java 1.6 environment and ex-CPP. http://www.prowiki.org/wiki4d/wiki.cgi?JavaToD I read this here. About 80-bit floats, I hoped that was about handling decimal point number without the use of a library like other language. Avoiding runtime error like: d1=func1(); // returns -0.0i; d2=func2(); // return 0.0i; if(d1==d2)... // some time that failed.
May 12 2011
Matthew Ong wrote:Hi Alexander, Is there anyway to ensure the comparison of float/double to be done with the raw bits like in Java Double.doubleToRawLongBits(double value) http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Double.html#doubleToRawLongBits%28double%29 when it comes to financial data and percentage computation, that seems to be rather important. Thanks in advance. Matthew Ongstd.math.isIdentical(). I doubt it would ever be appropriate to use this in a financial context, it's more for precise testing of math functions. Note that, for example, isIdentical(-0.0, +0.0) returns false.
May 13 2011
On 5/13/2011 3:12 PM, Don wrote:std.math.isIdentical(). I doubt it would ever be appropriate to use this in a financial context, it's more for precise testing of math functions. Note that, for example, isIdentical(-0.0, +0.0) returns false.Hi, Hmm.. That is main reason that I can see that why Java provided that function. Thanks. I will keep that in mind. In Java and most C/C++ does not have problem for <,>, for double/float type comparison. But when it comes to <=,>=,== we need to be very careful and need to somehow solve that with some sort of raw bits method. I cannot remember, there is one programming language(old one) does not have issue when it comes to financial data computation and also logical comparison. To handle that I have written some API in Java, looks like I need to port that over also. But let me bounce that off other to see if there is someone that have solved this before. -- Matthew Ong email: ongbp yahoo.com
May 16 2011
Thanks for the answer. I guess the correct technique would be to define an "equality" function with a tolerance within 1e-08. I guess I should head over to the TDLP errata section and point out that the example code needs to be fixed to allow for this possibility.
May 12 2011
On 5/12/11 11:00 AM, Abid H. Mujtaba wrote:Thanks for the answer. I guess the correct technique would be to define an "equality" function with a tolerance within 1e-08. I guess I should head over to the TDLP errata section and point out that the example code needs to be fixed to allow for this possibility.Thanks for considering adding to the errata. Which particular example on page 143 fails? Andrei
May 12 2011
Section 5.5 Overloading on page 142 it defines the following example of a "find" function which searches for slices within slices: T1[] find( T1, T2 )( T1[] longer, T2[] shorter ) if( is( typeof( longer[ 0 .. 1 ] == shorter ) : bool ) ) { while ( longer.length >= shorter.length ) { if ( longer[0 .. shorter.length] == shorter ) break ; } return longer ; } On page 143 it defines the following unittest : unittest { double[] d1 = [ 6.0, 1.5, 2.4, 3 ] ; float[] d2 = [ 1.5, 2.4 ] ; assert( find(d1,d2) == d1[1 .. $] ; } It is the assert() that fails since the comparison longer[0 .. shorter.length] == shorter fails because the comparison between the double and float values fails due to bit precision and representation issues.
May 12 2011
On 5/12/11 11:21 AM, Abid H. Mujtaba wrote:Section 5.5 Overloading on page 142 it defines the following example of a "find" function which searches for slices within slices: T1[] find( T1, T2 )( T1[] longer, T2[] shorter ) if( is( typeof( longer[ 0 .. 1 ] == shorter ) : bool ) ) { while ( longer.length>= shorter.length ) { if ( longer[0 .. shorter.length] == shorter ) break ; } return longer ; } On page 143 it defines the following unittest : unittest { double[] d1 = [ 6.0, 1.5, 2.4, 3 ] ; float[] d2 = [ 1.5, 2.4 ] ; assert( find(d1,d2) == d1[1 .. $] ; } It is the assert() that fails since the comparison longer[0 .. shorter.length] == shorter fails because the comparison between the double and float values fails due to bit precision and representation issues.I see. Thanks! I updated the errata with credit: http://erdani.com/tdpl/errata Andrei
May 12 2011
On 5/12/11 11:00 AM, Abid H. Mujtaba wrote:Thanks for the answer. I guess the correct technique would be to define an "equality" function with a tolerance within 1e-08. I guess I should head over to the TDLP errata section and point out that the example code needs to be fixed to allow for this possibility.Also, you may want to peruse the function approxEqual in std.math. Andrei
May 12 2011
Andrei:Also, you may want to peruse the function approxEqual in std.math.I suggest feqrel: http://www.digitalmars.com/d/2.0/phobos/std_math.html#feqrel Bye, bearophile
May 12 2011
The website defines the signature for feqrel to be: int feqrel(X)(X x, X y); It requires x and y to be the same type. But the variables we are working with are NOT the same type. This is what started the whole debate in the first place. I tested approxEqual and it works. Just have to be careful with the precision one uses.
May 12 2011