num_words 0.3.0 → 0.5.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: 24463f1da6ace2a42347b2e4bd275527a02510175087ebc98eaf3011ea56f4ff
4
- data.tar.gz: e61dc04d74d11bde0825d575a5240b96790d1a156ad8048813449adf1e267e05
3
+ metadata.gz: a0d117daa9a0ef678984f1a03b1b1456047e7ea67b4b13f610ab8cfb90634646
4
+ data.tar.gz: 4732ef7b105d1ae22b208529fe6098cbab124aef3547ee4650f3d24dd4b3a89e
5
5
  SHA512:
6
- metadata.gz: 9decb67c34898169365951b2c04c79449c0024ea83263ed30a8d0412ce1f6f2ac62a6423e380c9492cd87afce0841085e3f4e06900b9141a87427d4043fc8a04
7
- data.tar.gz: 2f5fe30029e8c3ed6915c0ace3f913d3ed3ea0f47ac119f200b1a8dc4b410e0575317f5011275bc40c466e1593af21732c918829b02bfa1a47cd5ac3f0709704
6
+ metadata.gz: 75c3b9d42dc93e10d5a413d2f1a03b04921f8277dd1ae056bcf4f020c9672e6e4737752d82d02541e9ac9b0560e0facb5888e64cb3de72ee83dcb881855f27b0
7
+ data.tar.gz: 666c1624f2d5c82ac29cd479f3c1625f0f43941be7876d190b3483ff87de195d4c949b9d88b74b9c10e8886f64e2657d91812ce85a2041fd5705d4038900208c
data/README.md CHANGED
@@ -13,8 +13,25 @@
13
13
  - **UK** – `thousand, million, billion`
14
14
  - **France** – `mille, million, milliard`
15
15
  - **India** – `thousand, lakh, crore`
16
+ - Supports multiple languages:
17
+ - **English** (`:en`)
18
+ - **Hindi** (`:hi`)
19
+ - **French** (`:fr`) *(optional / extended)*
16
20
  - Easy to integrate into Ruby or Rails applications.
17
21
  - Supports numbers up to `duovigintillion` (10^69) in the American system.
22
+ - Handles both integers and decimal numbers.
23
+
24
+ # In US system
25
+ - NumWords.to_words(123456789012345, country: :us, language: :en)
26
+ - "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"
27
+
28
+ # In Hindi
29
+ - NumWords.to_words(123456789012345, country: :hi, language: :hi)
30
+ - "बारह खरब चौतीस अरब छप्पन करोड़ सात करोड़ अस्सी लाख बारह हज़ार तीन सौ पैंतालीस"
31
+
32
+ # Indian number with decimals
33
+ - NumWords.to_words(1234567890.123, country: :in, language: :en)
34
+ - "one hundred and twenty-three crore forty-five lakh sixty-seven thousand eight hundred and ninety and one two three"
18
35
 
19
36
  ---
20
37
 
@@ -26,7 +43,10 @@ After releasing your gem to [RubyGems.org](https://rubygems.org), install it wit
26
43
 
27
44
  ```bash
28
45
  # Using Bundler
29
- bundle add gem 'num_words'
46
+ bundle add gem "num_words"
30
47
 
31
- # Or install manually
48
+ # Or using gem install
32
49
  gem install num_words
50
+
51
+
52
+
@@ -2,70 +2,94 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module NumWords
5
- ONES = %w[zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen].freeze
6
- TENS = %w[zero ten twenty thirty forty fifty sixty seventy eighty ninety].freeze
5
+ # --- English words ---
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
+ TENS_EN = %w[zero ten twenty thirty forty fifty sixty seventy eighty ninety].freeze
8
+
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
7
22
 
23
+ INDIAN_UNITS_HI = ['', 'हज़ार', 'लाख', 'करोड़', 'अरब', 'खरब'].freeze
8
24
  AM_EXPONENTS = {
9
25
  3 => 'thousand', 6 => 'million', 9 => 'billion', 12 => 'trillion',
10
26
  15 => 'quadrillion', 18 => 'quintillion', 21 => 'sexillion', 24 => 'septillion',
11
- 27 => 'octillion', 30 => 'nonillion', 33 => 'decillion', 36 => 'undecillion',
12
- 39 => 'duodecillion', 42 => 'tredecillion', 45 => 'quattuordecillion', 48 => 'quindecillion',
13
- 51 => 'sexdecillion', 54 => 'septendecillion', 57 => 'octodecillion', 60 => 'novemdecillion',
14
- 63 => 'vigintillion', 66 => 'unvigintillion', 69 => 'duovigintillion'
15
- }.freeze
16
-
17
- EU_EXPONENTS = {
18
- 3 => 'thousand', 6 => 'million', 9 => 'milliard', 12 => 'billion',
19
- 15 => 'billiard', 18 => 'trillion', 21 => 'trilliard', 24 => 'quadrillion',
20
- 27 => 'quadrilliard', 30 => 'quintillion', 33 => 'quintilliard', 36 => 'sextillion',
21
- 39 => 'sextilliard', 42 => 'septillion', 45 => 'septilliard', 48 => 'octillion',
22
- 51 => 'octilliard', 54 => 'noventillion', 57 => 'noventilliard', 60 => 'decillion',
23
- 63 => 'decilliard', 66 => 'undecillion', 69 => 'undecilliard'
24
- }.freeze
25
-
26
- UK_EXPONENTS = {
27
- 3 => 'thousand', 6 => 'million', 12 => 'billion', 15 => 'billiard',
28
- 18 => 'trillion', 21 => 'trilliard', 24 => 'quadrillion'
29
- }.freeze
30
-
31
- FR_EXPONENTS = {
32
- 3 => 'mille', 6 => 'million', 9 => 'milliard', 12 => 'billion',
33
- 15 => 'billiard', 18 => 'trillion', 21 => 'trilliard'
27
+ 27 => 'octillion', 30 => 'nonillion', 33 => 'decillion', 36 => 'undecillion'
34
28
  }.freeze
35
-
36
- INDIAN_UNITS = ['', 'thousand', 'lakh', 'crore'].freeze
29
+ INDIAN_UNITS_EN = ['', 'thousand', 'lakh', 'crore', 'arab', 'kharab'].freeze
37
30
 
38
31
  COUNTRY_EXPONENTS = {
39
32
  us: AM_EXPONENTS,
40
- eu: EU_EXPONENTS,
41
- uk: UK_EXPONENTS,
42
- fr: FR_EXPONENTS,
43
- in: INDIAN_UNITS
33
+ in: INDIAN_UNITS_EN
44
34
  }.freeze
45
35
 
46
36
  class << self
47
- def to_words(number, country: :us, include_and: true)
48
- return to_words_indian(number) if country == :in
37
+ # Convert number to words
38
+ def to_words(number, country: :us, language: :en, include_and: true)
39
+ if [:in].include?(country) && language == :hi
40
+ return to_words_indian(number)
41
+ end
49
42
 
50
43
  val = number.to_i.abs
51
44
  return 'zero' if val.zero?
52
45
 
53
46
  exp_hash = COUNTRY_EXPONENTS[country] || AM_EXPONENTS
54
- to_words_generic(val, exp_hash, include_and)
47
+ ones_array = language == :hi ? HINDI_NUMBERS_1_TO_99 : ONES_EN
48
+ tens_array = language == :hi ? HINDI_NUMBERS_1_TO_99 : TENS_EN
49
+ units = language == :hi ? INDIAN_UNITS_HI : INDIAN_UNITS_EN
50
+
51
+ if country == :in
52
+ to_words_indian(number, language: language)
53
+ else
54
+ to_words_generic(val, exp_hash, include_and, ones_array, tens_array)
55
+ end
55
56
  end
56
57
 
57
- def to_words_indian(num)
58
- integer_part, decimal_part = num.to_s.split('.')
59
- integer_words = indian_units_to_words(integer_part.to_i)
60
- return integer_words if decimal_part.nil? || decimal_part.to_i.zero?
58
+ # Indian system (Hindi & English)
59
+ def to_words_indian(num, language: :hi)
60
+ num = num.to_i
61
+ return HINDI_NUMBERS_1_TO_99[num] if num <= 99
61
62
 
62
- decimal_words = decimal_part.chars.map { |d| sub_thousand_to_words(d.to_i) }.join(' ')
63
- "#{integer_words} and #{decimal_words}"
63
+ words = []
64
+ unit_index = 0
65
+
66
+ loop do
67
+ break if num.zero?
68
+ num, remainder = unit_index.zero? ? num.divmod(1000) : num.divmod(100)
69
+ part = convert_hindi_sub_thousand(remainder)
70
+ words.unshift("#{part} #{INDIAN_UNITS_HI[unit_index]}".strip) if remainder.positive?
71
+ unit_index += 1
72
+ end
73
+
74
+ words.join(' ').strip
64
75
  end
65
76
 
66
77
  private
67
78
 
68
- def to_words_generic(val, exp_hash, include_and)
79
+ def convert_hindi_sub_thousand(num)
80
+ return HINDI_NUMBERS_1_TO_99[num] if num <= 99
81
+
82
+ words = []
83
+ if num >= 100
84
+ words << "#{HINDI_NUMBERS_1_TO_99[num / 100]} सौ"
85
+ num %= 100
86
+ end
87
+ words << HINDI_NUMBERS_1_TO_99[num] if num.positive?
88
+ words.join(' ').strip
89
+ end
90
+
91
+ # Generic system (English or other)
92
+ def to_words_generic(val, exp_hash, include_and, ones_array, tens_array)
69
93
  chunks = []
70
94
  while val.positive?
71
95
  chunks << val % 1000
@@ -75,55 +99,25 @@ module NumWords
75
99
  result = []
76
100
  chunks.each_with_index do |chunk, index|
77
101
  next if chunk.zero?
78
- words = hundreds_to_words(chunk, include_and && index.zero?)
102
+ words = hundreds_to_words(chunk, include_and && index.zero?, ones_array, tens_array)
79
103
  result.unshift("#{words} #{exp_hash[index * 3]}".strip)
80
104
  end
81
105
  result.join(' ').strip
82
106
  end
83
107
 
84
- def hundreds_to_words(val, include_and = false)
108
+ def hundreds_to_words(val, include_and, ones_array, tens_array)
85
109
  return '' if val.zero?
86
110
 
87
111
  words = []
88
112
  if val >= 100
89
- words << "#{ONES[val / 100]} hundred"
113
+ words << "#{ones_array[val / 100]} #{ones_array == HINDI_NUMBERS_1_TO_99 ? 'सौ' : 'hundred'}"
90
114
  val %= 100
91
- words << 'and' if val.positive? && include_and
92
- end
93
-
94
- words << TENS[val / 10] if val >= 20
95
- val %= 10 if val >= 20
96
- words << ONES[val] if val.positive?
97
- words.join(' ').strip
98
- end
99
-
100
- def indian_units_to_words(num)
101
- num = num.to_i
102
- return 'zero' if num.zero?
103
- words = []
104
- unit_index = 0
105
-
106
- loop do
107
- break if num.zero?
108
-
109
- num, remainder = unit_index.zero? ? num.divmod(1000) : num.divmod(100)
110
- words.unshift("#{sub_thousand_to_words(remainder)} #{INDIAN_UNITS[unit_index]}".strip) if remainder.positive?
111
- unit_index += 1
115
+ words << 'and' if val.positive? && include_and && ones_array != HINDI_NUMBERS_1_TO_99
112
116
  end
113
117
 
118
+ words << tens_array[val] if val > 0 && val <= 99 && ones_array == HINDI_NUMBERS_1_TO_99
119
+ words << ones_array[val] if val > 0 && val < 20 && ones_array != HINDI_NUMBERS_1_TO_99
114
120
  words.join(' ').strip
115
121
  end
116
-
117
- def sub_thousand_to_words(num)
118
- num = num.to_i
119
- return ONES[num] if num < 20
120
- return "#{ONES[num / 100]} hundred" if num >= 100 && (num % 100).zero?
121
-
122
- if num < 100
123
- "#{TENS[num / 10]} #{ONES[num % 10]}".strip
124
- else
125
- "#{ONES[num / 100]} hundred and #{sub_thousand_to_words(num % 100)}"
126
- end
127
- end
128
122
  end
129
123
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NumWords
4
- VERSION = "0.3.0"
4
+ VERSION = "0.5.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.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mrmalvi
@@ -24,11 +24,10 @@ files:
24
24
  - lib/num_words.rb
25
25
  - lib/num_words/converter.rb
26
26
  - lib/num_words/version.rb
27
- - num_words-0.1.0.gem
28
- - num_words-0.2.0.gem
29
27
  - sig/num_words.rbs
30
28
  homepage: https://github.com/mrmalvi/num_words
31
- licenses: []
29
+ licenses:
30
+ - MIT
32
31
  metadata:
33
32
  allowed_push_host: https://rubygems.org
34
33
  homepage_uri: https://github.com/mrmalvi/num_words
data/num_words-0.1.0.gem DELETED
Binary file
data/num_words-0.2.0.gem DELETED
Binary file