Newbie: How to format a number to always show two decimals?

Hi,

This seems like a simple task, yet I've been unable to accomplish it. Somewhere I read you could do:

num.round(2).to_s("F")

But that is not working, as the round method doesn't accept any parameters.

Could someone help me figure this out?

Thanks!

Ivan V.

Hi,

This seems like a simple task, yet I've been unable to accomplish it. Somewhere I read you could do:

num.round(2).to_s("F")

But that is not working, as the round method doesn't accept any parameters.

Could someone help me figure this out?

>> sprintf("%.2f", 1.012345)
=> "1.01"
>> # ... or ...
?> "%.2f" % 1.012345
=> "1.01"

Hope that helps.

James Edward Gray II

···

On Oct 31, 2005, at 4:47 PM, i.v.r. wrote:

James Edward Gray II wrote:

···

On Oct 31, 2005, at 4:47 PM, i.v.r. wrote:

Hi,

This seems like a simple task, yet I've been unable to accomplish it. Somewhere I read you could do:

num.round(2).to_s("F")

But that is not working, as the round method doesn't accept any parameters.

Could someone help me figure this out?

>> sprintf("%.2f", 1.012345)
=> "1.01"
>> # ... or ...
?> "%.2f" % 1.012345
=> "1.01"

Hope that helps.

James Edward Gray II

That was fast! Thanks a lot.

Alternatively there's this code from Phrogz's library (
http://phrogz.net/rubylibs\) which to me is more rubyish than sprintf.
Everytime you use sprintf, God kills a kitten.

-Harold

#Code Follows:

class Numeric
# Rounds to the specified number of decimal places, returning a string
value.

···

#
# (1.234).round_to(2) => '1.23'
# (-1.234).round_to(2) => '-1.23'
# (-0.007).round_to(2) => '-0.01'
# (-0.007).round_to(1) => '0.0'
def round_to(decimals)
if self<0 then
s='-';
x=-self;
else
s='';
x=self;
end
if x>=1.0e15 then
m=x.to_s;
else
m=(x*10**decimals).round.to_s
if (decimals!=0) then
k=m.length;
if k<=decimals then
z='000000000000000'[0..(decimals-k)]
m=z+m;
k=decimals+1;
end
m.insert(k-decimals,'.');
end
end
s='' if (/^0\.0*$/=~m);
s+m;
end
end

On 10/31/05, i.v.r. <ivanvega@gmail.com> wrote:

James Edward Gray II wrote:
> On Oct 31, 2005, at 4:47 PM, i.v.r. wrote:
>
>> Hi,
>>
>> This seems like a simple task, yet I've been unable to accomplish it.
>> Somewhere I read you could do:
>>
>> num.round(2).to_s("F")
>>
>> But that is not working, as the round method doesn't accept any
>> parameters.
>>
>> Could someone help me figure this out?
>
> >> sprintf("%.2f", 1.012345)
> => "1.01"
> >> # ... or ...
> ?> "%.2f" % 1.012345
> => "1.01"
>
> Hope that helps.
>
> James Edward Gray II
>
>
That was fast! Thanks a lot.

Hi --

···

On Tue, 1 Nov 2005, Harold Hausman wrote:

Alternatively there's this code from Phrogz's library (
http://phrogz.net/rubylibs\) which to me is more rubyish than sprintf.
Everytime you use sprintf, God kills a kitten.

-Harold

#Code Follows:

class Numeric
# Rounds to the specified number of decimal places, returning a string
value.
#
# (1.234).round_to(2) => '1.23'
# (-1.234).round_to(2) => '-1.23'
# (-0.007).round_to(2) => '-0.01'
# (-0.007).round_to(1) => '0.0'
def round_to(decimals)
if self<0 then
s='-';
x=-self;
else
s='';
x=self;
end
if x>=1.0e15 then
m=x.to_s;
else
m=(x*10**decimals).round.to_s
if (decimals!=0) then
k=m.length;
if k<=decimals then
z='000000000000000'[0..(decimals-k)]
m=z+m;
k=decimals+1;
end
m.insert(k-decimals,'.');
end
s='' if (/^0\.0*$/=~m);
s+m;
end

Aside to Phrogz: is that left over from a game of code golf?? :slight_smile:

David

--
David A. Black
dblack@wobblini.net

Hmm, it's certainly not Ruby length...

James Edward Gray II

···

On Oct 31, 2005, at 6:21 PM, Harold Hausman wrote:

Alternatively there's this code from Phrogz's library (
http://phrogz.net/rubylibs\) which to me is more rubyish than sprintf.

Alternatively there's this code from Phrogz's library (
http://phrogz.net/rubylibs\) which to me is more rubyish than sprintf.
Everytime you use sprintf, God kills a kitten.

that quote is absolutely beautiful - though i __much__ prefer printf to cout
:wink:

-Harold

#Code Follows:

class Numeric
# Rounds to the specified number of decimal places, returning a string
value.
#
# (1.234).round_to(2) => '1.23'
# (-1.234).round_to(2) => '-1.23'
# (-0.007).round_to(2) => '-0.01'
# (-0.007).round_to(1) => '0.0'
def round_to(decimals)
if self<0 then
s='-';
x=-self;
else
s='';
x=self;
end
if x>=1.0e15 then
m=x.to_s;
else
m=(x*10**decimals).round.to_s
if (decimals!=0) then
k=m.length;
if k<=decimals then
z='000000000000000'[0..(decimals-k)]
m=z+m;
k=decimals+1;
end
m.insert(k-decimals,'.');
end
s='' if (/^0\.0*$/=~m);
s+m;
end

James Edward Gray II wrote:

Hi,

This seems like a simple task, yet I've been unable to accomplish it.
Somewhere I read you could do:

num.round(2).to_s("F")

But that is not working, as the round method doesn't accept any
parameters.

Could someone help me figure this out?

sprintf("%.2f", 1.012345)

=> "1.01"

# ... or ...

?> "%.2f" % 1.012345
=> "1.01"

Hope that helps.

James Edward Gray II

That was fast! Thanks a lot.

-a

···

On Tue, 1 Nov 2005, Harold Hausman wrote:

On 10/31/05, i.v.r. <ivanvega@gmail.com> wrote:

On Oct 31, 2005, at 4:47 PM, i.v.r. wrote:

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
anything that contradicts experience and logic should be abandoned.
-- h.h. the 14th dalai lama

===============================================================================

What's wrong with sprintf? I don't see how sprintf is evil versus the long procedure you detailed, but what do I know... I'm just a BASIC programmer, LOL.

Ivan

Harold Hausman wrote:

···

Alternatively there's this code from Phrogz's library (
http://phrogz.net/rubylibs\) which to me is more rubyish than sprintf.
Everytime you use sprintf, God kills a kitten.

-Harold

#Code Follows:

class Numeric
# Rounds to the specified number of decimal places, returning a string
value.
#
# (1.234).round_to(2) => '1.23'
# (-1.234).round_to(2) => '-1.23'
# (-0.007).round_to(2) => '-0.01'
# (-0.007).round_to(1) => '0.0'
def round_to(decimals)
if self<0 then
s='-';
x=-self;
else
s='';
x=self;
end
if x>=1.0e15 then
m=x.to_s;
else
m=(x*10**decimals).round.to_s
if (decimals!=0) then
k=m.length;
if k<=decimals then
z='000000000000000'[0..(decimals-k)]
m=z+m;
k=decimals+1;
end
m.insert(k-decimals,'.');
end
s='' if (/^0\.0*$/=~m);
s+m;
end

On 10/31/05, i.v.r. <ivanvega@gmail.com> wrote:
  

James Edward Gray II wrote:
    

On Oct 31, 2005, at 4:47 PM, i.v.r. wrote:

Hi,

This seems like a simple task, yet I've been unable to accomplish it.
Somewhere I read you could do:

num.round(2).to_s("F")

But that is not working, as the round method doesn't accept any
parameters.

Could someone help me figure this out?
        

sprintf("%.2f", 1.012345)
          

=> "1.01"
      

# ... or ...
          

?> "%.2f" % 1.012345
=> "1.01"

Hope that helps.

James Edward Gray II

That was fast! Thanks a lot.

In that case...
"%.2f" % 1.012345
=> "1.01"

···

On Oct 31, 2005, at 7:21 PM, Harold Hausman wrote:

Alternatively there's this code from Phrogz's library (
http://phrogz.net/rubylibs\) which to me is more rubyish than sprintf.
Everytime you use sprintf, God kills a kitten.

-Harold

LOL. No, before I grokked sprintf, I needed the round_to functionality. That's a port of the Number.toFixed algorithm from section 15.7.4.5 of the ECMAScript (ECMA-262) specs:

15.7.4.5 Number.prototype.toFixed (fractionDigits)
Return a string containing the number represented in fixed-point notation with fractionDigits digits after the decimal point. If fractionDigits is undefined, 0 is assumed. Specifically, perform the following steps:

1. Let Ä be ToInteger(fractionDigits). (If fractionDigits is undefined, this step produces the value 0).
2. If Ä < 0 or Ä > 20, t hrow a RangeError exception.
3. Let x be this number value.
4. If x is NaN, return the string "NaN".
5. Let s be t he empty string.
6. I f x ³ 0, go to step 9.
7. Let s be "-".
8. Let x = Ðx.
9. I f x ³ 10^21, let m = ToString(x) and go to step 20.
10. Let n be an integer for which the exact mathematical value of n Ö 10^Ä Ð x is as close to zero as possible. If there are two such n, pick t he larger n.
11. I f n = 0, let m be the string "0". Otherwise, let m be the string consisting of the digits of the decimal representation of n (in order, with no leading zeroes).
12. If Ä = 0, go to step 20.
13. Let k be the number of characters in m.
14. If k > Ä, go to step 18.
15. Let z be the string consisting of Ä +1Ðk occurrences of the character Ô0Õ.
16. Let m be the concatenation of strings z and m.
17. Let k = Ä + 1.
18. Let a be the first kÐÄ characters of m, and let b be the remaining Ä characters of m.
19. Let m be the concatenation of the three strings a, ".", and b.
20. Return the concatenation of the strings s and m.

···

On Oct 31, 2005, at 5:41 PM, David A. Black wrote:

Aside to Phrogz: is that left over from a game of code golf?? :slight_smile:

Quoting "i.v.r." <ivanvega@gmail.com>:

What's wrong with sprintf? I don't see how sprintf is evil versus
the long procedure you detailed, but what do I know... I'm just a
BASIC programmer, LOL.

There's nothing wrong with using sprintf (aka format) here. It's
just not the most readable or flexible solution in many other
cases.

Since sprintf() is lifted almost directly from C, recent converts
from C do have a tendency to overuse it. That and its distinctly
C-ish flavor likely account for Harold's revulsion.

Now, not being a former C programmer, you may not be so strongly
tempted to write:

sprintf("%s%s%s", a.zolum, b.fep, c.gorza)

when you could have simply written:

"#{a.zolum}#{b.fep}#{c.gorza}"

...but if you ever are, please be aware that it's worth TWO kittens.

-mental

Hi --

···

On Tue, 1 Nov 2005, Gavin Kistner wrote:

On Oct 31, 2005, at 5:41 PM, David A. Black wrote:

Aside to Phrogz: is that left over from a game of code golf?? :slight_smile:

LOL. No, before I grokked sprintf, I needed the round_to functionality. That's a port of the Number.toFixed algorithm from section 15.7.4.5 of the ECMAScript (ECMA-262) specs:

Interesting pedigree.

It was the semi-colons and the vacuum-packed syntax that made me think
it might be a multi-line split-out of a former golf entry :slight_smile:

David

--
David A. Black
dblack@wobblini.net

Hi --

Quoting "i.v.r." <ivanvega@gmail.com>:

What's wrong with sprintf? I don't see how sprintf is evil versus
the long procedure you detailed, but what do I know... I'm just a
BASIC programmer, LOL.

There's nothing wrong with using sprintf (aka format) here. It's
just not the most readable or flexible solution in many other
cases.

Since sprintf() is lifted almost directly from C, recent converts
from C do have a tendency to overuse it. That and its distinctly
C-ish flavor likely account for Harold's revulsion.

Now, not being a former C programmer, you may not be so strongly
tempted to write:

sprintf("%s%s%s", a.zolum, b.fep, c.gorza)

when you could have simply written:

"#{a.zolum}#{b.fep}#{c.gorza}"

...but if you ever are, please be aware that it's worth TWO kittens.

I think one of the common rites of passage into Ruby is going from
this:

   printf("%s\n", string);

to this:

   puts string

:slight_smile: Mind you, as a scanf author I do root for that family of methods
a bit. scanf, when conditions allow its use, can actually save you a
lot of .to_i-ing and such.

David

···

On Wed, 2 Nov 2005, mental@rydia.net wrote:

--
David A. Black
dblack@wobblini.net

mental@rydia.net wrote:

Quoting "i.v.r." <ivanvega@gmail.com>:

What's wrong with sprintf? I don't see how sprintf is evil versus
the long procedure you detailed, but what do I know... I'm just a
BASIC programmer, LOL.
    
There's nothing wrong with using sprintf (aka format) here. It's
just not the most readable or flexible solution in many other
cases.

Since sprintf() is lifted almost directly from C, recent converts
from C do have a tendency to overuse it. That and its distinctly
C-ish flavor likely account for Harold's revulsion.

Now, not being a former C programmer, you may not be so strongly
tempted to write:

sprintf("%s%s%s", a.zolum, b.fep, c.gorza)

when you could have simply written:

"#{a.zolum}#{b.fep}#{c.gorza}"

...but if you ever are, please be aware that it's worth TWO kittens.

-mental

Ah, I see.

I'm actually very familiar with the second approach, so that's what I always use. So don't worry, no kittens will die by my hand :slight_smile:

- Ivan

mental@rydia.net wrote:

Now, not being a former C programmer, you may not be so strongly
tempted to write:

sprintf("%s%s%s", a.zolum, b.fep, c.gorza)

when you could have simply written:

"#{a.zolum}#{b.fep}#{c.gorza}"

..but if you ever are, please be aware that it's worth TWO kittens.

That reminds me, what are the options for nicely text formatted table
output? I usually use something like:
[a.zolum, b.feb, c.gorza].inject("") { |row,col| row.concat "%7s" % col
}

Are there better alternatives?

- alan

Ah, no. Upon reflection, those are because the ruby code is actually a port of my JavaScript version of that algorithm. Microsoft's own implementation of Number.toFixed did not (at some point, perhaps currently) conform to that algorithm (and other JS engines did not at some point support that method, despite it being part of the spec) so I wrote my own JS-only port to patch bad engines as needed. When it came time to for the Ruby version, a bit of syntax conversion seems to be all I did.

At the point in my life when I wrote the JS version, I was very into very terse formatting. Whitespace seemed to be at a premium during that dark period. :slight_smile:

···

On Nov 1, 2005, at 7:49 AM, David A. Black wrote:

On Tue, 1 Nov 2005, Gavin Kistner wrote:

On Oct 31, 2005, at 5:41 PM, David A. Black wrote:

Aside to Phrogz: is that left over from a game of code golf?? :slight_smile:

LOL. No, before I grokked sprintf, I needed the round_to functionality. That's a port of the Number.toFixed algorithm from section 15.7.4.5 of the ECMAScript (ECMA-262) specs:

Interesting pedigree.

It was the semi-colons and the vacuum-packed syntax that made me think
it might be a multi-line split-out of a former golf entry :slight_smile:

Alan Chen wrote:

That reminds me, what are the options for nicely text formatted table
output? I usually use something like:
[a.zolum, b.feb, c.gorza].inject("") { |row,col| row.concat "%7s" % col
}

Are there better alternatives?

- alan

irb(main):001:0> a=[1,2,3,4]
=> [1, 2, 3, 4]
irb(main):002:0> ("%7s " * a.size) % a
=> " 1 2 3 4 "

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

If your cols are strings:

[a.zolum, b.feb, c.gorza].map { |col| col.rjust(7) }.join

If they aren't you have to add to_s:

[a.zolum, b.feb, c.gorza].map { |col| col.to_s.rjust(7) }.join

Dominik

···

On Thu, 03 Nov 2005 01:57:09 +0100, Alan Chen <Digikata@gmail.com> wrote:

mental@rydia.net wrote:

Now, not being a former C programmer, you may not be so strongly
tempted to write:

sprintf("%s%s%s", a.zolum, b.fep, c.gorza)

when you could have simply written:

"#{a.zolum}#{b.fep}#{c.gorza}"

..but if you ever are, please be aware that it's worth TWO kittens.

That reminds me, what are the options for nicely text formatted table
output? I usually use something like:
[a.zolum, b.feb, c.gorza].inject("") { |row,col| row.concat "%7s" % col
}

Are there better alternatives?

You can also use max() to get the size, instead of a magic number.

James Edward Gray II

···

On Nov 3, 2005, at 7:56 AM, Dominik Bathon wrote:

If your cols are strings:

[a.zolum, b.feb, c.gorza].map { |col| col.rjust(7) }.join

If they aren't you have to add to_s:

[a.zolum, b.feb, c.gorza].map { |col| col.to_s.rjust(7) }.join