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

Discussion in 'Ruby' started by Max Williams, May 15, 2009.

  1. Max Williams

    Max Williams Guest

    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-forum.com/.
    Max Williams, May 15, 2009
    #1
    1. Advertising

  2. 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://agileconsultingllc.com
    Rob Biedenharn, May 15, 2009
    #2
    1. Advertising

  3. On Sat, May 16, 2009 at 1:57 AM, 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
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >


    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/list.html
    Harry Kakueki, May 16, 2009
    #3
  4. Max Williams

    Robert Dober Guest

    On Fri, May 15, 2009 at 6: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. =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-forum.com/.
    >
    >

    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.
    Robert Dober, May 16, 2009
    #4
  5. Max Williams

    Max Williams Guest

    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-forum.com/.
    Max Williams, May 16, 2009
    #5
  6. Max Williams

    Max Williams Guest

    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-forum.com/.
    Max Williams, May 16, 2009
    #6
  7. 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://agileconsultingllc.com
    Rob Biedenharn, May 16, 2009
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steve
    Replies:
    5
    Views:
    42,639
    Steve
    May 17, 2004
  2. Jeremy Watts

    more than 16 significant figures

    Jeremy Watts, Jul 4, 2005, in forum: Java
    Replies:
    32
    Views:
    1,288
    Tom N
    Jul 15, 2005
  3. bd
    Replies:
    0
    Views:
    597
  4. Alf P. Steinbach

    Re: Round to significant figures (C++)

    Alf P. Steinbach, May 1, 2006, in forum: C++
    Replies:
    0
    Views:
    713
    Alf P. Steinbach
    May 1, 2006
  5. SMH
    Replies:
    0
    Views:
    206
Loading...

Share This Page