Issue #8299 has been updated by naruse (Yui NARUSE).


I wrote this is because of x87.
Did you read it?

marcandre (Marc-Andre Lafortune) wrote:
> naruse (Yui NARUSE) wrote:
> > > 1) Float#to_s must be minimal while round-tripping. This is clearly not the case in the given examples.
> > 
> > If the given value cannot be represented by binary, it won't be minimal while round-tripping.
> 
> Sorry, I do not understand what you said. What I meant to say is ([ruby-core:30145]):
> 
> For any float f, the two following conditions should hold:
> (1) f.to_s.to_f == f        (round trips)

Yeah, unless you transfer the result of to_s to another environment.

> (2) f.to_s.chop.to_f != f   (minimal)
>
> The second condition is a simplification; if the string representation is in scientific notation, than the character to remove would be the one just before the "e". Also, if the string representation ends with ".0", then it is minimal.

The same as above.

> > > 2) Float#to_s must be platform independent
> > 
> > double calculation itself is platform dependent.
> 
> Sorry, I should have specified "...on IEEE 754 platforms", which is the case for mgwin32, right?
> 
> > Moreover there's non IEEE-754 fp for example VAX.
> 
> We don't support VAX, as you wrote yourself in [ruby-core:42077], so how is this relevant exactly?

I had written VAX but the main subject of here is x87 FPU.

On 32bit IA (yeah, this is also reproducible on 32bit Linux), program usually calculates floating point numbers with x87 FPU.
x87 FPU stores and calculates floating numbers in 80bit on registers, even if it is stored in 64bit on memory.
Therefore x87's result may differ from modern FPU's result.

For example -1.1505945e-05,
On modern FPU, it is stored/expressed as -0x1.821350a1d1742p-17, and this is converted to -1.1505945E-05 in decimal.
But on x87 FPU this is expressed as -0x1.821350a1d1741800p-17, and converted to -1.1505945000000001E-05 in decimal.
Yeah, this can be avoided by storing it to memory by specifying volatile, but this costs time and make code complex.
On gcc, specifying -ffloat-store or -fexcess-precision=standard (gcc 4.5) is more simple, but this is also slows down.
On modern x86 CPU it has SSE, so specify -msse2 -mfpmath=sse is easy way.
# Note that Xeon Phi has x87 and 512bit SMID, but doesn't have SSE
----------------------------------------
Bug #8299: Minor error in float parsing
https://bugs.ruby-lang.org/issues/8299#change-38803

Author: bobjalex (Bob Alexander)
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 
ruby -v: trunk
Backport: 


I encountered a float that either parses [slightly] differently (or converts to string differently) in Ruby than it does in Python or Java. This looks like a  Ruby bug since the result "looks" incorrect.

It is easily reproduced by entering the magic number (-1.1505945E-5) into irb. It behaves the same in 2.0 and 1.9. I'm using Windows.

Below is an irb session that demonstrates. Also included are JRuby and Python trials that show better behavior.

This issue is not causing me any problems, but just in case someone there is interested in looking into it...

Bob

>ruby -v
ruby 2.0.0p0 (2013-02-24) [i386-mingw32]

>irb
irb(main):001:0> RUBY_VERSION
=> "2.0.0"
irb(main):002:0> -1.1505945E-5
=> -1.1505945000000001e-05

>ruby19 -v
ruby 1.9.3p392 (2013-02-22) [i386-mingw32]

>irb19
irb(main):001:0> RUBY_VERSION
=> "1.9.3"
irb(main):002:0> -1.1505945E-5
=> -1.1505945000000001e-05
irb(main):002:0>

>jirb
irb(main):001:0> -1.1505945E-5
=> -1.1505945e-05

>python
Python 2.7.4rc1 (default, Mar 24 2013, 14:34:32) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> -1.1505945E-5
-1.1505945e-05
>>> repr(-1.1505945E-5)
'-1.1505945e-05'




-- 
http://bugs.ruby-lang.org/