[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Rounding any number (int or float) to 3 significant figures

Max Williams

5/15/2009 4:57:00 PM

I have a requirement where i need to display (ie convert to a string)
all digits to 3 significant figures. (not the same as 3 decimal places)

eg

23 => "23"
26759 => "26,800"
10.546 => "10.5"
3332332 => "3,330,000"
0.766 => "0.766"
0.00000766 => "0.00000766"

Can anyone show me a neat way to do this? I'd have thought that there'd
be a method for it already but i can't find one.

thanks!
max
--
Posted via http://www.ruby-....

6 Answers

Rob Biedenharn

5/15/2009 5:46:00 PM

0


On May 15, 2009, at 12:57 PM, Max Williams wrote:

> I have a requirement where i need to display (ie convert to a string)
> all digits to 3 significant figures. (not the same as 3 decimal
> places)
>
> eg
>
> 23 => "23"
> 26759 => "26,800"
> 10.546 => "10.5"
> 3332332 => "3,330,000"
> 0.766 => "0.766"
> 0.00000766 => "0.00000766"
>
> Can anyone show me a neat way to do this? I'd have thought that
> there'd
> be a method for it already but i can't find one.
>
> thanks!
> max
> --

This should get you started:

irb> h.each do |n,s|
irb> puts( ("%f"%[("%.3g"%n).to_f]).sub(/\.?0*\z/,'') )
irb> end
0.766
23
26800
10.5
3330000
0.000008
=> {0.766=>"0.766", 23=>"23", 26759=>"26,800", 10.546=>"10.5",
3332332=>"3,330,000", 7.66e-06=>"0.00000766"}

It doesn't do so well with the smallest value, but if you know the
ranges you're dealing with, perhaps you can adjust the %f spec.

-Rob

Rob Biedenharn http://agileconsult...
Rob@AgileConsultingLLC.com


Harry Kakueki

5/16/2009 6:43:00 AM

0

On Sat, May 16, 2009 at 1:57 AM, Max Williams
<toastkid.williams@gmail.com> wrote:
> I have a requirement where i need to display (ie convert to a string)
> all digits to 3 significant figures. (not the same as 3 decimal places)
>
> eg
>
> 23 => "23"
> 26759 => "26,800"
> 10.546 => "10.5"
> 3332332 => "3,330,000"
> 0.766 => "0.766"
> 0.00000766 => "0.00000766"
>
> Can anyone show me a neat way to do this? I'd have thought that there'd
> be a method for it already but i can't find one.
>
> thanks!
> max
> --
> Posted via http://www.ruby-....
>
>

Sorry, but I don't have much time that I can spend to come up with a
better answer right now.
But, I thought I would throw this idea your way.
Check it carefully (it may have bugs) and maybe you can make improvements.


require 'bigdecimal'

arr = [23,26759,10.546,3332332,0.766,0.00000766]
arr.each do |x|
m = 2 - Math.log10(x).floor
p BigDecimal.new(((x*10**m).round*10**(-1*m)).to_s).to_s('F').gsub(/\.0*$/,"")
end

#output
##########
#> "23"
#> "26800"
#> "10.5"
#> "3330000"
#> "0.766"
#> "0.00000766"


Harry

--
A Look into Japanese Ruby List in English
http://www.kakueki.com/ruby...

Robert Dober

5/16/2009 9:07:00 AM

0

On Fri, May 15, 2009 at 6:57 PM, Max Williams
<toastkid.williams@gmail.com> wrote:
> I have a requirement where i need to display (ie convert to a string)
> all digits to 3 significant figures. =A0(not the same as 3 decimal places=
)
>
> eg
>
> =A0 =A023 =3D> "23"
> =A0 =A026759 =3D> "26,800"
> =A0 =A010.546 =3D> "10.5"
> =A0 =A03332332 =3D> "3,330,000"
> =A0 =A00.766 =3D> "0.766"
> =A0 =A00.00000766 =3D> "0.00000766"
>
> Can anyone show me a neat way to do this? =A0I'd have thought that there'=
d
> be a method for it already but i can't find one.
>
> thanks!
> max
> --
> Posted via http://www.ruby-....
>
>
At frirst sight and testing with the data you have given, the
following pretty much seems to do the trick:

x.to_s.sub( /(\.0*\d{0,3}).*/, '\1' )

Did I overlook any edge cases?

HTH
R.

Max Williams

5/16/2009 11:06:00 AM

0

Thanks rob!

I combined that with the rails helper 'number_with_delimiter, and it
works great:

def number_to_n_significant_digits(number, n = 3)
("%f"%[("%.#{n}g"%number).to_f]).sub(/\.?0*\z/,'')
end

#in my other method
number_with_delimiter(number_to_n_significant_digits(number))

I don't think the 0.0000008 instead of 0.000000766 case will be a
problem.

My next quest is to work out what's going on in your code snippet.
I can see that the sub at the end removes trailing zeros, right?

And the first part looks like some oldschool c-style string
substitution, time to pull out the pickaxe :)

thanks again!
max
--
Posted via http://www.ruby-....

Max Williams

5/16/2009 11:25:00 AM

0

A great bunch of solutions, thanks a lot guys. More nice tasks for me
trying to reverse engineer them as well (especially Harry's Math
solution) :)

cheers!
max
--
Posted via http://www.ruby-....

Rob Biedenharn

5/16/2009 1:25:00 PM

0

On May 16, 2009, at 7:06 AM, Max Williams wrote:

> Thanks rob!
>
> I combined that with the rails helper 'number_with_delimiter, and it
> works great:
>
> def number_to_n_significant_digits(number, n = 3)
> ("%f"%[("%.#{n}g"%number).to_f]).sub(/\.?0*\z/,'')
> end
>
> #in my other method
> number_with_delimiter(number_to_n_significant_digits(number))
>
> I don't think the 0.0000008 instead of 0.000000766 case will be a
> problem.

Okey-dokey! "soft" requirement for the win!
>
>
> My next quest is to work out what's going on in your code snippet.
> I can see that the sub at the end removes trailing zeros, right?

Yes, in English it says:

If there is a series of 0's (0*) at the end of the string (\z)
possibly preceeded by a decimal point (\.?), replace all that with
nothing (i.e., delete it).

>
>
> And the first part looks like some oldschool c-style string
> substitution, time to pull out the pickaxe :)
>
> thanks again!
> max


String#% will direct you to Kernel#sprintf, but you're already on the
right track.

-Rob

Rob Biedenharn http://agileconsult...
Rob@AgileConsultingLLC.com