Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Why is Float#to_s not returning what I'd expect?
>> 12345678901234566.0.to_s
=> "12345678901234566.0"
>> 12345678901234567.0.to_s
=> "12345678901234568.0"
>> 12345678901234568.0.to_s
=> "12345678901234568.0"
>> 12345678901234569.0.to_s
=> "12345678901234568.0"
>> 123456789012345678.0.to_s
=> "123456789012345680.0"
@rjfranco

That's ... no good.

@marcandre

Which one of those do you think is an error?

@marcandre

12345678901234567.to_s(2).length == 54
Floats can only store 53 bits, so it its float equivalent is inexact.

@jc00ke
Owner

@marcandre

12345678901234569.0.to_s
=> "12345678901234568.0"

but I guess my assumption is wrong. I understand the precision issue when they are actually floats, but as strings I would expect them to be a digit-for-digit copy as a string, that's all.

@marcandre

They can't be a digit-for-digit copy, as that requires way too much information!

Are you really expecting 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475.to_s to be over 200 characters long?

Ruby converts to string with the following algo: the most accurate of the simplest decimal expansion that uniquely maps to that float representation. I.e. you are guaranteed that it round trips any_float.to_s.to_f == any_float, it is unique, i.e. float_a.to_s == float_b.to_s if and only if float_a == float_b. It's simplest in that you can't remove a decimal of the string without changing the resulting float.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.