You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Sebb (JIRA)" <ji...@apache.org> on 2011/01/13 00:31:45 UTC

[jira] Created: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

MathUtils.equals(double, double) does not work properly for floats
------------------------------------------------------------------

                 Key: MATH-471
                 URL: https://issues.apache.org/jira/browse/MATH-471
             Project: Commons Math
          Issue Type: Bug
            Reporter: Sebb


MathUtils.equals(double, double) does not work properly for floats.

There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.

So for example:

{code}
double oneDouble = 1.0d;
assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
float oneFloat = 1.0f;
assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
float  f1 = 333.33334f;
double d1 = 333.33334d;
assertTrue(MathUtils.equals(d1, f1)); // FAILS
{code}

I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.


-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Sebb (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12981807#action_12981807 ] 

Sebb commented on MATH-471:
---------------------------

Many of the double-only methods work OK with widened float parameters.

Where this is not the case, we either need to fix the discrepancy (as per this JIRA) or document the restriction.

I don't see the point of separating the utilities into two different classes, but if the consensus is that we should, then we need to make sure that the same methods are present in both, even if the double method works perfectly well, otherwise it would be even more confusing for users (where do I find the method?).

But I think the main issue is that having a separate class would force users to *edit and recompile* to take advantage of any fixes such as this one.

> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Sebb (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Sebb updated MATH-471:
----------------------

    Attachment: Math471.patch

Implementation of equals(float...) methods

> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Phil Steitz (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12982136#action_12982136 ] 

Phil Steitz commented on MATH-471:
----------------------------------

I agree with Sebb on this one.  I think it is a bug (the second example).  The promotion separates the values that are indistinguishable as floats.  Consistently with comments on MATH-474, equals(-,-) should identify indiscernibles.  I also agree that it is better to just add the methods to MathUtils.


> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Resolved: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Sebb (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Sebb resolved MATH-471.
-----------------------

       Resolution: Fixed
    Fix Version/s: 3.0
                   2.2

Patches now applied.

> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>             Fix For: 2.2, 3.0
>
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Sebb (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12981020#action_12981020 ] 

Sebb commented on MATH-471:
---------------------------

I now realise that the 3rd example above may not be easy - or even possible - to fix, but it does offer a good example of the difficulties of comparing floating point numbers!

> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] [Closed] (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Luc Maisonobe (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Luc Maisonobe closed MATH-471.
------------------------------


Closing issue as it was included in version 2.2, which has been released

> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>             Fix For: 2.2, 3.0
>
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] Commented: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Gilles (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12981216#action_12981216 ] 

Gilles commented on MATH-471:
-----------------------------

{quote}
MathUtils.equals(double, double) does not work properly for floats.

There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
{quote}

This is not a bug, but expected behaviour. But I certainly agree that it does not hurt to mention the conversion issue for the unwary.

However, shouldn't there be emphasis, in the user guide, that CM is a "double" precision library? A quick poll of the code gives the following numbers:
Occurrences of the string "float ": *41* (roughly half of which were introduced with this patch)
Occurrences of the string "double ": *4061*

Also, I'm curious as to what use case you were having that requires comparing {{float}} numbers.

Finally if we want to help users avoid such pitfalls, I think that we should consider refactoring {{MathUtils}} so that similar methods that should behave differently for different types are in _different_ classes (exactly as with classes {{Float}} and {{Double}}). Thus, we should create {{MathUtilsDouble}} (or assume that the current {{MathUtils}} is for {{double}} utilities) and {{MathUtilsFloat}}.



> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Sebb (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12981107#action_12981107 ] 

Sebb commented on MATH-471:
---------------------------

Just had a thought:

I don't think the exactly same code can be added to 2.x, because the semantics of some of the double methods has changed.
It would be confusing if floats behaved differently from doubles!

So I propose to rework the fix for 2.x to preserve the deprecated behaviour and deprecated tags.

OK?

> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Sebb (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12981091#action_12981091 ] 

Sebb commented on MATH-471:
---------------------------

Yes, I think the 3rd example is not relevant to the immediate problem (although indirectly it was what alerted me to the problem).

Though it may perhaps be worthwhile noting the conversion issue somewhere in the Javadoc - perhaps at class level?

> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Phil Steitz (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12981074#action_12981074 ] 

Phil Steitz commented on MATH-471:
----------------------------------

It is not obvious to me that the third example should succeed.  An argument could be made that the existing code does the right thing when passed a double and a float, which is to convert the float according to the value set conversion rules and then compare the result to the double.  

> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Phil Steitz (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12981049#action_12981049 ] 

Phil Steitz commented on MATH-471:
----------------------------------

Ouch!

Thanks for reporting and patching this. Sebb.  

+1 for applying the patch to both 2_X and trunk, with unit tests.

> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (MATH-471) MathUtils.equals(double, double) does not work properly for floats

Posted by "Phil Steitz (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/MATH-471?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12981108#action_12981108 ] 

Phil Steitz commented on MATH-471:
----------------------------------

Yes, you are right.  Needs to be reworked slightly for 2.x.

> MathUtils.equals(double, double) does not work properly for floats
> ------------------------------------------------------------------
>
>                 Key: MATH-471
>                 URL: https://issues.apache.org/jira/browse/MATH-471
>             Project: Commons Math
>          Issue Type: Bug
>            Reporter: Sebb
>         Attachments: Math471.patch
>
>
> MathUtils.equals(double, double) does not work properly for floats.
> There is no equals(float,float) so float parameters are automatically promoted to double. However, that is not necessarily appropriate, given that the ULP for a double is much smaller than the ULP for a float.
> So for example:
> {code}
> double oneDouble = 1.0d;
> assertTrue(MathUtils.equals(oneDouble, Double.longBitsToDouble(1 + Double.doubleToLongBits(oneDouble)))); // OK
> float oneFloat = 1.0f;
> assertTrue(MathUtils.equals(oneFloat, Float.intBitsToFloat(1 + Float.floatToIntBits(oneFloat)))); // FAILS
> float  f1 = 333.33334f;
> double d1 = 333.33334d;
> assertTrue(MathUtils.equals(d1, f1)); // FAILS
> {code}
> I think the equals() methods need to be duplicated with the appropriate changes for floats to avoid any problems with the promotion of floats.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.