# Printf with octal numbers

**URL:** <https://rubytalk.org/t/printf-with-octal-numbers/16063>\
**Category:** ruby-talk\
**Created:** [26 January 2005 23:34 UTC](https://rubytalk.org/t/printf-with-octal-numbers/16063 "2005-01-26T23:34:27Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Brooks\_Davis](https://avatars.discourse-cdn.com/v4/letter/b/d07c76/32.png) [@Brooks\_Davis](https://rubytalk.org/u/Brooks_Davis)\
**Post date:** [26 January 2005 23:34 UTC](https://rubytalk.org/t/printf-with-octal-numbers/16063/1 "2005-01-26T23:34:27Z")

</div>

The behavior of sprintf("%d", str) is not what I would expect. If str  
begins with a '0', for example "01", it is treated as an octal number.  
This seem odd because I would expect the following two lines to be the  
same:

sprintf("%d", str)  
sprintf("%d", str.to\_i)

This is not the case:

irb(main):006:0\> str="08"  
=\> "08"  
irb(main):007:0\> sprintf("%d", str)  
ArgumentError: invalid value for Integer: "08"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):7:in `sprintf'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):7  
irb(main):008:0\> sprintf("%d", str.to\_i)  
=\> "8"  
irb(main):009:0\> str="010"  
=\> "010"  
irb(main):010:0\> sprintf("%d", str)  
=\> "8"  
irb(main):011:0\> sprintf("%d", str.to\_i)  
=\> "10"

The seems to violate POLA. In my case it was quite astonishing because  
I had a script where I parse strings like "r01rpc2" to find the rack and  
power controller number from a string. When I added my eighth rack, the  
script stopped working after several years of operation. Is this  
behavior intended? The documentation on rubycentral doesn't really say  
one way or another.

In case it matters, my ruby version is:

[12:15pm] brooks@minya (~/working/cluster/power): ruby -v  
ruby 1.8.2 (2004-07-29) [i386-freebsd6]

Thanks,  
Brooks

> **···**
>
> --  
> Any statement of the form "X is the one, true Y" is FALSE.  
> PGP fingerprint 655D 519C 26A7 82E7 2529 9BF0 5D8E 8BE9 F238 1AD4

---

<div class="post-metadata">

**Author:** ![David\_Sletten](https://avatars.discourse-cdn.com/v4/letter/d/b3f665/32.png) [@David\_Sletten](https://rubytalk.org/u/David_Sletten)\
**Post date:** [27 January 2005 02:25 UTC](https://rubytalk.org/t/printf-with-octal-numbers/16063/2 "2005-01-27T02:25:56Z")

</div>

Brooks Davis wrote:

> The behavior of sprintf("%d", str) is not what I would expect. If str  
> begins with a '0', for example "01", it is treated as an octal number.  
> This seem odd because I would expect the following two lines to be the  
> same:
> 
> sprintf("%d", str)  
> sprintf("%d", str.to\_i)
> 
> This is not the case:
> 
> irb(main):006:0\> str="08"  
> =\> "08"  
> irb(main):007:0\> sprintf("%d", str)  
> ArgumentError: invalid value for Integer: "08"  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):7:in `sprintf'  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):7  
> irb(main):008:0\> sprintf("%d", str.to\_i)  
> =\> "8"  
> irb(main):009:0\> str="010"  
> =\> "010"  
> irb(main):010:0\> sprintf("%d", str)  
> =\> "8"  
> irb(main):011:0\> sprintf("%d", str.to\_i)  
> =\> "10"
> 
> The seems to violate POLA. In my case it was quite astonishing because  
> I had a script where I parse strings like "r01rpc2" to find the rack and  
> power controller number from a string. When I added my eighth rack, the  
> script stopped working after several years of operation. Is this  
> behavior intended? The documentation on rubycentral doesn't really say  
> one way or another.

This behavior is a little odd. The documentation for String#to\_i (A bit out of date here: [http://www.rubycentral.com/book/ref\_c\_string.html#String.to\_i\](http://www.rubycentral.com/book/ref_c_string.html#String.to_i%5C)) says that if no arg is passed to to\_i(), then the default base is 10. The string is then evaluated in that base, so leading 0's are ignored. If a base of 0 is given, then to\_i() looks for leading '0', '0b', '0o', '0d', or '0x' to determine the base. The method never raises an exception, but returns 0 instead when no valid number is found.  
Thus:  
irb(main):255:0\> "08".to\_i  
=\> 8  
irb(main):256:0\> "08".to\_i(0) #Viewed as octal. '8' is invalid digit.  
=\> 0  
irb(main):257:0\> "07".to\_i(0) #Octal  
=\> 7  
irb(main):258:0\> "7".to\_i(0) #Decimal  
=\> 7

sprintf() appears to interpret numeric strings differently--in line with the rules for numeric literals in Ruby:  
irb(main):261:0\> 08  
SyntaxError: compile error  
(irb):261: Illegal octal digit  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):261  
irb(main):262:0\> sprintf("%d", "08")  
ArgumentError: invalid value for Integer: "08"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):262:in `sprintf'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from (irb):262  
irb(main):263:0\> sprintf("%d", "0d8")  
=\> "8"

I would suggest you stick with explicitly calling to\_i.

David Sletten
