num_words 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dcb338b276c0afbc161d4ede15bb75c6f64fd279be42066ecabb9c2c986be10c
4
- data.tar.gz: 60b8112d1ad8729eb652d7acd893b1cd1e5aa83b5ac31a200ff8df06ca83a4a8
3
+ metadata.gz: c707e6c57aaf783107cb3290b903a117e012ce6c187d01eb9c6845c709c247a3
4
+ data.tar.gz: 8cde67422c55d5ebc89d90a70992af08a5f8404cdc121b250adf901e5ded661d
5
5
  SHA512:
6
- metadata.gz: e12980e8da746190aa011b645978741ac7c7dbc2ce5c9dc91c8fa6ebae3ca4dd57d25b81295d3d28294fc417e7ca0dc3536e45cead806363fcc62122c633442b
7
- data.tar.gz: 42dc76855150a5c44fa7cce78d6fa401ec4e161ee6808642dfded60919d65b5ec01bee2b939b288f37ac5dd16948c556b5f79a8f7d5f9cd8af2536c58f580e5f
6
+ metadata.gz: f7d41d25b31437a63ac7ae7efd4e91c9ae930fc52b087f5c83951d28a4accf70b8e5c1bb88019822630afdb5a846da9406f81ee99c9564760a0f90b60afd4961
7
+ data.tar.gz: 2d94b537a8db62c48749bb0ae149efb58d91c976e334fb0aec48f1e9649b6146b5d89671d9ef1f8b063ee8144ea53086166f98e7a2a7ce2c3391ea5cc6183fea
data/README.md CHANGED
@@ -9,12 +9,26 @@
9
9
  - Convert integers and decimals to words.
10
10
  - Supports multiple country numbering systems:
11
11
  - **US / American** – `thousand, million, billion`
12
- - **European** – `thousand, million, milliard, billion`
13
- - **UK** – `thousand, million, billion`
14
- - **France** – `mille, million, milliard`
15
12
  - **India** – `thousand, lakh, crore`
13
+ - Supports multiple languages:
14
+ - **English** (`:en`)
15
+ - **Hindi** (`:hi`)
16
+ - **French** (`:fr`) *(optional / extended)*
16
17
  - Easy to integrate into Ruby or Rails applications.
17
18
  - Supports numbers up to `duovigintillion` (10^69) in the American system.
19
+ - Handles both integers and decimal numbers.
20
+
21
+ # In US system
22
+ - NumWords.to_words(123456789012345, country: :us, language: :en)
23
+ - "one hundred and twenty-three trillion four hundred and fifty-six billion seven hundred and eighty-nine million twelve thousand three hundred and forty-five"
24
+
25
+ # In Hindi
26
+ - NumWords.to_words(123456789012345, country: :hi, language: :hi)
27
+ - "बारह खरब चौतीस अरब छप्पन करोड़ सात करोड़ अस्सी लाख बारह हज़ार तीन सौ पैंतालीस"
28
+
29
+ # Indian number with decimals
30
+ - NumWords.to_words(1234567890.123, country: :in, language: :en)
31
+ - "one hundred and twenty-three crore forty-five lakh sixty-seven thousand eight hundred and ninety and one two three"
18
32
 
19
33
  ---
20
34
 
@@ -26,6 +40,10 @@ After releasing your gem to [RubyGems.org](https://rubygems.org), install it wit
26
40
 
27
41
  ```bash
28
42
  # Using Bundler
29
- bundle add num_words
43
+ bundle add gem "num_words"
44
+
45
+ # Or using gem install
46
+ gem install num_words
47
+
48
+
30
49
 
31
- bundle add num_words
@@ -6,10 +6,23 @@ module NumWords
6
6
  ONES_EN = %w[zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen].freeze
7
7
  TENS_EN = %w[zero ten twenty thirty forty fifty sixty seventy eighty ninety].freeze
8
8
 
9
- # --- Hindi words ---
10
- ONES_HI = %w[शून्य एक दो तीन चार पाँच छह सात आठ नौ दस ग्यारह बारह तेरह चौदह पंद्रह सोलह सत्रह अठारह उन्नीस].freeze
11
- TENS_HI = %w[शून्य दस बीस तीस चालीस पचास साठ सत्तर अस्सी नब्बे].freeze
9
+ # --- Hindi numbers 1 to 99 (pure Hindi) ---
10
+ HINDI_NUMBERS_1_TO_99 = {
11
+ 0=>"शून्य",1=>"एक",2=>"दो",3=>"तीन",4=>"चार",5=>"पाँच",6=>"छह",7=>"सात",8=>"आठ",9=>"नौ",10=>"दस",
12
+ 11=>"ग्यारह",12=>"बारह",13=>"तेरह",14=>"चौदह",15=>"पंद्रह",16=>"सोलह",17=>"सत्रह",18=>"अठारह",19=>"उन्नीस",
13
+ 20=>"बीस",21=>"इक्कीस",22=>"बाईस",23=>"तेईस",24=>"चौबीस",25=>"पच्चीस",26=>"छब्बीस",27=>"सत्ताईस",28=>"अट्ठाईस",29=>"उनतीस",
14
+ 30=>"तीस",31=>"इकतीस",32=>"बत्तीस",33=>"तैंतीस",34=>"चौंतीस",35=>"पैंतीस",36=>"छत्तीस",37=>"सैंतीस",38=>"अड़तीस",39=>"उनतालीस",
15
+ 40=>"चालीस",41=>"इकतालीस",42=>"बयालीस",43=>"तैंतालीस",44=>"चवालीस",45=>"पैंतालीस",46=>"छियालीस",47=>"सैंतालीस",48=>"अड़तालीस",49=>"उनचास",
16
+ 50=>"पचास",51=>"इक्यावन",52=>"बावन",53=>"तिरेपन",54=>"चौवन",55=>"पचपन",56=>"छप्पन",57=>"सत्तावन",58=>"अट्ठावन",59=>"उनसठ",
17
+ 60=>"साठ",61=>"इकसठ",62=>"बासठ",63=>"तिरेसठ",64=>"चौंसठ",65=>"पैंसठ",66=>"छियासठ",67=>"सड़सठ",68=>"अड़सठ",69=>"उनहत्तर",
18
+ 70=>"सत्तर",71=>"इकहत्तर",72=>"बहत्तर",73=>"तिहत्तर",74=>"चौहत्तर",75=>"पचहत्तर",76=>"छिहत्तर",77=>"सतहत्तर",78=>"अठहत्तर",79=>"उन्यासी",
19
+ 80=>"अस्सी",81=>"इक्यासी",82=>"बयासी",83=>"तिरेासी",84=>"चौरासी",85=>"पचासी",86=>"छियासी",87=>"सत्तासी",88=>"अठासी",89=>"नवासी",
20
+ 90=>"नब्बे",91=>"इक्यानवे",92=>"बयानवे",93=>"तिरेनवे",94=>"चौरानवे",95=>"पचानवे",96=>"छियानवे",97=>"सत्तानवे",98=>"अट्ठानवे",99=>"निन्यानवे"
21
+ }.freeze
22
+
23
+ # --- Units ---
12
24
  INDIAN_UNITS_HI = ['', 'हज़ार', 'लाख', 'करोड़', 'अरब', 'खरब'].freeze
25
+ INDIAN_UNITS_EN = ['', 'thousand', 'lakh', 'crore', 'arab', 'kharab'].freeze
13
26
 
14
27
  # --- English exponents ---
15
28
  AM_EXPONENTS = {
@@ -18,87 +31,33 @@ module NumWords
18
31
  27 => 'octillion', 30 => 'nonillion', 33 => 'decillion', 36 => 'undecillion'
19
32
  }.freeze
20
33
 
21
- INDIAN_UNITS_EN = ['', 'thousand', 'lakh', 'crore', 'arab', 'kharab'].freeze
22
-
23
34
  COUNTRY_EXPONENTS = {
24
35
  us: AM_EXPONENTS,
25
36
  in: INDIAN_UNITS_EN
26
37
  }.freeze
27
38
 
28
39
  class << self
29
- # Main method: convert number to words
30
- # language: :en or :hi
40
+ # Convert number to words
41
+ # Default language: :en
31
42
  def to_words(number, country: :us, language: :en, include_and: true)
32
- if [:in].include?(country) && language == :hi
33
- return to_words_indian(number, language: language)
34
- end
35
-
36
43
  val = number.to_i.abs
37
- return 'zero' if val.zero?
38
-
39
- exp_hash = COUNTRY_EXPONENTS[country] || AM_EXPONENTS
40
- ones_array = language == :hi ? ONES_HI : ONES_EN
41
- tens_array = language == :hi ? TENS_HI : TENS_EN
42
- units = language == :hi ? INDIAN_UNITS_HI : INDIAN_UNITS_EN
44
+ return language == :hi ? HINDI_NUMBERS_1_TO_99[0] : 'zero' if val.zero?
43
45
 
44
46
  if country == :in
45
- to_words_indian(number, language: language)
46
- else
47
- to_words_generic(val, exp_hash, include_and, ones_array, tens_array)
47
+ return language == :hi ? to_words_indian(number) : to_words_indian(number, language: :en)
48
48
  end
49
- end
50
-
51
- # Indian system (supports English & Hindi)
52
- def to_words_indian(num, language: :en)
53
- integer_part, decimal_part = num.to_s.split('.')
54
- ones_array = language == :hi ? ONES_HI : ONES_EN
55
- tens_array = language == :hi ? TENS_HI : TENS_EN
56
- units = language == :hi ? INDIAN_UNITS_HI : INDIAN_UNITS_EN
57
49
 
58
- integer_words = indian_units_to_words(integer_part.to_i, ones_array, tens_array, units)
59
- return integer_words if decimal_part.nil? || decimal_part.to_i.zero?
60
-
61
- decimal_words = decimal_part.chars.map { |d| sub_thousand_to_words(d.to_i, ones_array, tens_array) }.join(' ')
62
- "#{integer_words} and #{decimal_words}"
63
- end
64
-
65
- private
66
-
67
- def to_words_generic(val, exp_hash, include_and, ones_array, tens_array)
68
- chunks = []
69
- while val.positive?
70
- chunks << val % 1000
71
- val /= 1000
72
- end
73
-
74
- result = []
75
- chunks.each_with_index do |chunk, index|
76
- next if chunk.zero?
77
- words = hundreds_to_words(chunk, include_and && index.zero?, ones_array, tens_array)
78
- result.unshift("#{words} #{exp_hash[index * 3]}".strip)
79
- end
80
- result.join(' ').strip
81
- end
82
-
83
- def hundreds_to_words(val, include_and, ones_array, tens_array)
84
- return '' if val.zero?
85
-
86
- words = []
87
- if val >= 100
88
- words << "#{ones_array[val / 100]} #{ones_array == ONES_HI ? 'सौ' : 'hundred'}"
89
- val %= 100
90
- words << 'and' if val.positive? && include_and && ones_array != ONES_HI
91
- end
92
-
93
- words << tens_array[val / 10] if val >= 20
94
- val %= 10 if val >= 20
95
- words << ones_array[val] if val.positive?
96
- words.join(' ').strip
50
+ exp_hash = COUNTRY_EXPONENTS[country] || AM_EXPONENTS
51
+ ones_array = language == :hi ? HINDI_NUMBERS_1_TO_99 : ONES_EN
52
+ tens_array = language == :hi ? HINDI_NUMBERS_1_TO_99 : TENS_EN
53
+ to_words_generic(val, exp_hash, include_and, ones_array, tens_array)
97
54
  end
98
55
 
99
- def indian_units_to_words(num, ones_array, tens_array, units)
56
+ # Indian system (supports English & Hindi)
57
+ def to_words_indian(num, language: :hi)
100
58
  num = num.to_i
101
- return ones_array[0] if num.zero?
59
+ return HINDI_NUMBERS_1_TO_99[num] if language == :hi && num <= 99
60
+ return ONES_EN[num] if language == :en && num <= 19
102
61
 
103
62
  words = []
104
63
  unit_index = 0
@@ -106,30 +65,56 @@ module NumWords
106
65
  loop do
107
66
  break if num.zero?
108
67
  num, remainder = unit_index.zero? ? num.divmod(1000) : num.divmod(100)
109
- words.unshift("#{sub_thousand_to_words(remainder, ones_array, tens_array)} #{units[unit_index]}".strip) if remainder.positive?
68
+ part = language == :hi ? convert_hindi_sub_thousand(remainder) : convert_english_sub_thousand(remainder)
69
+ unit_name = language == :hi ? INDIAN_UNITS_HI[unit_index] : INDIAN_UNITS_EN[unit_index]
70
+ words.unshift("#{part} #{unit_name}".strip) if remainder.positive?
110
71
  unit_index += 1
111
72
  end
112
73
 
113
74
  words.join(' ').strip
114
75
  end
115
76
 
116
- def sub_thousand_to_words(num, ones_array, tens_array)
117
- return ones_array[num] if num < 20
118
- return "#{ones_array[num / 100]} #{ones_array == ONES_HI ? 'सौ' : 'hundred'}" if num >= 100 && (num % 100).zero?
77
+ private
119
78
 
79
+ def convert_hindi_sub_thousand(num)
80
+ return HINDI_NUMBERS_1_TO_99[num] if num <= 99
120
81
  words = []
121
82
  if num >= 100
122
- words << "#{ones_array[num / 100]} #{ones_array == ONES_HI ? 'सौ' : 'hundred'}"
83
+ words << "#{HINDI_NUMBERS_1_TO_99[num / 100]} सौ"
123
84
  num %= 100
124
85
  end
86
+ words << HINDI_NUMBERS_1_TO_99[num] if num.positive?
87
+ words.join(' ').strip
88
+ end
125
89
 
126
- if num >= 20
127
- words << tens_array[num / 10]
128
- num %= 10
90
+ def convert_english_sub_thousand(num)
91
+ return ONES_EN[num] if num < 20
92
+ words = []
93
+ if num >= 100
94
+ words << "#{ONES_EN[num / 100]} hundred"
95
+ num %= 100
129
96
  end
130
-
131
- words << ones_array[num] if num.positive?
97
+ words << TENS_EN[num / 10] if num >= 20
98
+ num %= 10 if num >= 20
99
+ words << ONES_EN[num] if num.positive?
132
100
  words.join(' ').strip
133
101
  end
102
+
103
+ def to_words_generic(val, exp_hash, include_and, ones_array, tens_array)
104
+ chunks = []
105
+ while val.positive?
106
+ chunks << val % 1000
107
+ val /= 1000
108
+ end
109
+
110
+ result = []
111
+ chunks.each_with_index do |chunk, index|
112
+ next if chunk.zero?
113
+ words = convert_english_sub_thousand(chunk)
114
+ words = "and #{words}" if include_and && index.zero? && chunk >= 100
115
+ result.unshift("#{words} #{exp_hash[index * 3]}".strip)
116
+ end
117
+ result.join(' ').strip
118
+ end
134
119
  end
135
120
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NumWords
4
- VERSION = "0.4.0"
4
+ VERSION = "0.6.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: num_words
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mrmalvi
@@ -9,8 +9,8 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
- description: NumWords gem converts integers and decimals to words. Supports US, EU,
13
- UK, FR, and Indian number systems with proper handling of decimals.
12
+ description: NumWords gem converts integers and decimals to words. Supports US and
13
+ Indian number systems with proper handling of decimals.
14
14
  email:
15
15
  - malviyak00@gmail.com
16
16
  executables: