# Precision loss with pack/unpack?

**URL:** <https://www.ruby-forum.com/t/precision-loss-with-pack-unpack/111691>\
**Category:** Ruby\
**Created:** [August 9, 2007, 9:07pm UTC](https://www.ruby-forum.com/t/precision-loss-with-pack-unpack/111691 "2007-08-09T21:07:50Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![luispulidoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/dec6dc/32.png) [@luispulidoman](https://www.ruby-forum.com/u/luispulidoman)\
**Post date:** [August 9, 2007, 9:07pm UTC](https://www.ruby-forum.com/t/precision-loss-with-pack-unpack/111691/1 "2007-08-09T21:07:50Z")

</div>

Hello

I’m reading Java class files using ruby and found some problems when  
handling float values. The numbers are stored using IEEE 754 format.  
After several hours trying and thinking I might be using unpack the  
wrong way, I’ve wrote the following code which packs a Float and then  
immediately unpacks it. And the result is different from the original  
value.

* * *

a = 0.1234567  
b = [a].pack(‘g’).unpack(‘g’)[0]

## puts “#{a} =? #{b} =\> #{a == b}”

outputs:

0.1234567 =? 0.123456701636314 =\> false

I came accross this doc, which states that in Perl this happens too  
([pack - Perldoc Browser](http://perldoc.perl.org/functions/pack.html)) “Note that Perl uses  
doubles internally for all numeric calculation, and converting from  
double into float and thence back to double again will lose precision  
(i.e., unpack(“f”, pack(“f”, $foo)) will not in general equal $foo).”  
Maybe Ruby is doing the same Perl does?

Any help will be appreciated

Thanks

---

<div class="post-metadata">

**Author:** ![luispulidoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/dec6dc/32.png) [@luispulidoman](https://www.ruby-forum.com/u/luispulidoman)\
**Post date:** [August 9, 2007, 9:40pm UTC](https://www.ruby-forum.com/t/precision-loss-with-pack-unpack/111691/2 "2007-08-09T21:40:53Z")

</div>

On 8/9/07, Luis P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> a = 0.1234567  
> b = [a].pack(‘g’).unpack(‘g’)[0]

Hmm I am not sure that this is exactly related but I would rather find  
this behavior normal, given my old memories of floating number  
representation, look at this e.g.

irb(main):004:0\> 0.1234567 + 1000 - 1000  
=\> 0.12345670000002

If you use enough bits you are fine:

b = [a].pack(‘G’).unpack(‘G’)

HTH  
Robert

---

<div class="post-metadata">

**Author:** ![luispulidoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/dec6dc/32.png) [@luispulidoman](https://www.ruby-forum.com/u/luispulidoman)\
**Post date:** [August 9, 2007, 11:13pm UTC](https://www.ruby-forum.com/t/precision-loss-with-pack-unpack/111691/3 "2007-08-09T23:13:07Z")

</div>

On Thursday 09 August 2007 12:06:31 pm Luis P. wrote:

> Hello
> 
> I’m reading Java class files using ruby and found some problems when  
> handling float values. The numbers are stored using IEEE 754 format.  
> After several hours trying and thinking I might be using unpack the  
> wrong way, I’ve wrote the following code which packs a Float and then  
> immediately unpacks it. And the result is different from the original  
> value.

Yes, small differences are common with floats. The best way to compare  
them  
is with something like that demonstrated in:  
[http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm#\_Toc135149455](http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm#_Toc135149455)

> I came accross this doc, which states that in Perl this happens too  
> ([pack - Perldoc Browser](http://perldoc.perl.org/functions/pack.html)) “Note that Perl uses  
> doubles internally for all numeric calculation, and converting from  
> double into float and thence back to double again will lose precision  
> (i.e., unpack(“f”, pack(“f”, $foo)) will not in general equal $foo).”  
> Maybe Ruby is doing the same Perl does?

Ruby uses doubles internally for floats as well. Loss of precision is  
common, but the above link should work well for you.

> Any help will be appreciated
> 
> Thanks

No problem, glad to (try to) help.

---

<div class="post-metadata">

**Author:** ![luispulidoman](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/dec6dc/32.png) [@luispulidoman](https://www.ruby-forum.com/u/luispulidoman)\
**Post date:** [August 10, 2007, 3:21am UTC](https://www.ruby-forum.com/t/precision-loss-with-pack-unpack/111691/4 "2007-08-10T03:21:25Z")

</div>

On 10 Tha ng Tám, 02:06, “Luis P.” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> outputs:
> 
> 0.1234567 =? 0.123456701636314 =\> false

It’s quite common with float or double representation. Because float/  
double can not represent ALL value within its range so some loss  
precision happens. It may happen right after assignment:  
eg: On my machine:

> a = a= 100.1001001003333  
> a  
> 100.100100100333 (the last digit gone?)
