Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Add Integer.nearestFloat, and make Integer.float a bit more useful #5637

Closed
CeylonMigrationBot opened this issue Sep 20, 2015 · 8 comments
Closed

Comments

@CeylonMigrationBot
Copy link

[@ePaul] Summary

  • Make Integer.float more liberal, allowing conversions whenever they are exact.
  • Introduce an Integer.nearestFloat to allow lossy conversions to Float.

Details
During the review of #5634, we noted that Integer's float attribute throws an exception whenever the value is ±2^53 or beyond. The reason for this is that Float (and Java's double) have only 53 bits of mantissa, so larger Integer values can not always be represented exactly as a Float.

But some of those values actually can be represented exactly, namely those which are a multiple of a suitable power of two so the other factor fits into 53 bits. These are exactly those values which also can result from Float.integer (for Floats in the range [-2^(-63)..(2^63-2^10)] or something similar).

Those Integers can be checked in Java by value == (long)(double)value, or in Ceylon by int.nearestFloat.integer == int with the nearestFloat attribute discussed below. (I didn't use int.float.integer == int, because we are just talking about the implementation of float.)

Thus I propose to extend the definition of Integer.float to only throw an exception in those cases where the Integer value is not representable exactly as a Float value.


In other cases we might not need an exact conversion to Float, but just some Float nearby (ideally the nearest one). An example is Ceylon-SDK issue #5174.

This currently can be emulated using the fact that the arithmetic operators do an automatic promotion from Integer to Float: int + 0.0 (or int * 1.0) gives the nearest Float value to int.

I propose to make this more explicit by adding a nearestFloat attribute to the Integer class, returning the nearest float to the integer value, and never throwing an OverflowException. That might be implemented in Ceylon as above (arithmetically), or in Java as a simple cast to double: (double)value.

[Migrated from ceylon/ceylon.language#759]

@CeylonMigrationBot
Copy link
Author

[@gavinking] @ePaul I'm assigning this to 1.3 because it's not blocking the 1.2 release. However, if you submit a patch I'll be happy to review/merge it. OK?

@CeylonMigrationBot
Copy link
Author

[@gavinking]

Thus I propose to extend the definition of Integer.float to only throw an exception in those cases where the Integer value is not representable exactly as a Float value.

But is this really useful. That's not clear to me. I don't see why you would happen to have a very large integer that just happens to be exactly representable as a float. That's especially true as they get larger, since the representable integers get further and further apart.

@CeylonMigrationBot
Copy link
Author

[@gavinking]

I propose to make this more explicit by adding a nearestFloat attribute to the Integer class, returning the nearest float to the integer value, and never throwing an OverflowException.

I agree we need this.

@CeylonMigrationBot
Copy link
Author

[@lucaswerkmeister]

Thus I propose to extend the definition of Integer.float to only throw an exception in those cases where the Integer value is not representable exactly as a Float value.

But is this really useful. That's not clear to me. I don't see why you would happen to have a very large integer that just happens to be exactly representable as a float. That's especially true as they get larger, since the representable integers get further and further apart.

I agree, this doesn’t sound very useful, and potentially harmful because something might randomly work where it’s expected to fail.

@CeylonMigrationBot
Copy link
Author

[@ePaul] Okay, I'll submit a pull request for nearestFloat ... and scrap the "extending float idea.

(I hate that "Comment and Close Issue" button.)

@CeylonMigrationBot
Copy link
Author

[@jvasileff]

This currently can be emulated using the fact that the arithmetic operators do an automatic promotion from Integer to Float: int + 0.0 (or int * 1.0) gives the nearest Float value to int.

Haha, nice. Much better than some code I wrote for this, which even involved promotion!

shared Float impreciseFloat(Integer|Float i)
    =>  if (is Float i) then
            i
        else if (realInts
                && (i >= 9007199254740992 ||
                    i <= -9007199254740992)) then
            (i / 9007199254740992).float
                * 9007199254740992
                + i % 9007199254740992
        else
            i.float;

@CeylonMigrationBot
Copy link
Author

[@jvasileff] Should we discuss if we still want the OverflowException prior to adding the new property? I initially liked the idea, but, my comment from the other thread:

I'm also starting to wonder about the value of the OverflowException as I change a bunch of code to use a new Float impreciseFloat(Integer) function. The thing is, the correctness is fleeting since the expectation is that you'll lose precision anyway once you start using the float.

Are there cases where we really benefit by having the exception? If so, should the exception be the default, or should there be something like preciseFloat or exactFloat?

@CeylonMigrationBot CeylonMigrationBot added this to the 1.3 milestone Nov 14, 2015
quintesse pushed a commit that referenced this issue Nov 14, 2015
The Java implementation is a simple cast, the JavaScript implementation does the same as `Number.float` (i.e. calls `Float(this.valueOf())`.
quintesse pushed a commit that referenced this issue Nov 14, 2015
quintesse pushed a commit that referenced this issue Nov 14, 2015
@gavinking
Copy link
Contributor

This was already fixed in Ceylon 1.2.

@gavinking gavinking modified the milestones: 1.2, 1.3 Mar 18, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants