SitePoint Sponsor

User Tag List

Results 1 to 3 of 3
  1. #1
    SitePoint Enthusiast jitao's Avatar
    Join Date
    Feb 2003
    Location
    Shanghai
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Question convert string to integer

    Hi I have a question and need your help.

    How can I convert a string like "6.09B" to an integer 6,090,000,000 or "34.2M" to 34,200,000 ?

    which method should I use can you give me a example?

    Thank you!

  2. #2
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    There are a number of ways you could do it, but the simplest is probably to create a new class to handle the conversion. For example, you could create a StringTo class and use that to handle various conversions. For your current problem you'd use a class method of 'integer', so it would look something like this:
    Code:
    number = StingTo.integer("6.09B")
    So to do this, you'd first write a unit test class. This is what I ended up with:
    Code:
    $:.unshift File.join(File.dirname(__FILE__),'..','lib')
    
    require 'test/unit'
    require 'string_to'
    
    class TestStringTo < Test::Unit::TestCase
      def setup
        @decimal_text = "1.1"
        @integer_text = "100"
        @fraction_text = ".45"
        @invalid_text = "X"
        @invalid_postscript = "1.1X"
        @valid_test_strings = [@decimal_text, @integer_text, @fraction_text]
      end
      
      def test_millions
        for test_string in @valid_test_strings
          @string = "#{test_string}M"
          @target = (test_string.to_f * (10**6)).to_i
          assert_output_matches_target
        end
      end
    
      def test_billions
        for test_string in @valid_test_strings
          @string = "#{test_string}B"
          @target = (test_string.to_f * (10**9)).to_i
          assert_output_matches_target
        end
      end
    
      def test_decimal
        for test_string in @valid_test_strings
          @string = "#{test_string}"
          @target = test_string.to_i
          assert_output_matches_target
        end
      end
    
      def test_invalid
        assert_raise RuntimeError do
          StringTo.integer(@invalid_text)
        end
        assert_raise NoMethodError do
          StringTo.integer(@invalid_postscript)
        end
      end
    
      private
      def assert_output_matches_target
        assert_equal @target, StringTo.integer(@string)
      end
    end
    As you write the test you can start writing the class. This is what I ended up with:
    Code:
    class StringTo
      CONVERSIONS = {'M' => 6, 'B' => 9}
    
      def self.integer(string)
        number_followed_by_single_letter_pattern = /^(\d+|\d+\.\d*|\d*\.\d+)(\D)$/
        number_only_pattern = /^(\d+|\d+\.\d*|\d*\.\d+)$/
        if string =~ number_followed_by_single_letter_pattern
          return ($1.to_f * (10 ** CONVERSIONS[$2])).to_i
        elsif string =~ number_only_pattern
          return string.to_i
        else
          raise
        end
      end
    end

  3. #3
    SitePoint Enthusiast jitao's Avatar
    Join Date
    Feb 2003
    Location
    Shanghai
    Posts
    42
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thankyou, this is awesome. I'll follow your every post, my lord.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •