ziffern 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +21 -0
  3. data/ziffern.rb +115 -0
  4. data/ziffern_spec.rb +89 -0
  5. metadata +89 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 784b7651963c3d172aa3bcf7e404760f3260eefa
4
+ data.tar.gz: 75236a977a0952a3a342bc443e66dfdad03cafac
5
+ SHA512:
6
+ metadata.gz: 074a40b8cc9ab7bc119f7c9c505c0e1709cc906f012ba6b4b79b6198bb0a6b09ca09e59acde4f755810f25b59cb896db4c78af1165be399e53991a37487dbaec
7
+ data.tar.gz: 088340abdc8033fa0175629cacf60dd3a1f4c4195ade5b290aaecc6ab414d5af89a2e719b780d367e3ef948bd29d14acec593b29bc77e108250d77d73aecd338
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Ziffern
2
+
3
+ **Number to text, in _German_!**
4
+
5
+ Handles _positive and negative_ numbers up to **125 digits**, with _unlimited decimals_.
6
+
7
+ ```ruby
8
+ require 'ziffern'
9
+ converter = Ziffern.new
10
+
11
+ [1, -5, 12345, 99.99, '0.00', 10**63 + 1].each do |number|
12
+ puts converter.to_german(number)
13
+ end
14
+
15
+ # >> eins
16
+ # >> minus fünf
17
+ # >> zwölftausenddreihundertfünfundvierzig
18
+ # >> neunundneunzig Komma neun neun
19
+ # >> null Komma null null
20
+ # >> eine Dezilliarde eins
21
+ ```
data/ziffern.rb ADDED
@@ -0,0 +1,115 @@
1
+ class Ziffern
2
+
3
+ # http://de.wikipedia.org/wiki/Zahlennamen
4
+
5
+ NINETEEN = %w{ null ein zwei drei vier fünf sechs sieben acht neun zehn elf zwölf
6
+ dreizehn vierzehn fünfzehn sechzehn siebzehn achtzehn neunzehn }
7
+
8
+ TENS = %w{ zwanzig dreißig vierzig fünfzig sechzig siebzig achtzig neunzig }.unshift(nil, nil)
9
+
10
+ BIG = %w{ M B Tr Quadr Quint Sext Sept Okt Non Dez Undez Dodez Tredez
11
+ Quattuordez Quindez Sedez Septendez Dodevigint Undevigint Vigint }.flat_map do |prefix|
12
+ %W( #{prefix}illion #{prefix}illiarde )
13
+ end
14
+
15
+
16
+ def to_german(number)
17
+ convert_integer(number) + convert_decimals(number)
18
+ end
19
+
20
+ private
21
+
22
+ def convert_integer(number)
23
+ number = number.to_i
24
+ return 'eins' if number == 1
25
+ return "minus #{convert_integer(number.abs)}" if number < 0
26
+
27
+ convert(number)
28
+ end
29
+
30
+ def convert(number)
31
+ case number
32
+ when 0..19 then NINETEEN[number]
33
+ when 20..99 then twenty_to_99(number)
34
+ when 100..999 then quantify_factor(100, 'hundert', number)
35
+ when 1000..999_999 then quantify_factor(1000, 'tausend', number)
36
+ else bignums(number)
37
+ end
38
+ end
39
+
40
+ def twenty_to_99(number)
41
+ ten, remainder = number.divmod(10)
42
+
43
+ if remainder.zero?
44
+ TENS[ten]
45
+ else
46
+ "#{NINETEEN[remainder]}und#{TENS[ten]}"
47
+ end
48
+ end
49
+
50
+ def quantify_factor(factor, name, number)
51
+ amount, remainder = number.divmod(factor)
52
+
53
+ result = convert(amount) + name
54
+ result.tap do |result|
55
+ result << convert(remainder) unless remainder.zero?
56
+ end
57
+ end
58
+
59
+ def bignums(number)
60
+ number_of_millions, remainder = number.divmod(1000_000)
61
+
62
+ convert_millions(number_of_millions).tap do |result|
63
+ result << " " << convert_integer(remainder) unless remainder.zero?
64
+ end
65
+ end
66
+
67
+ def convert_millions(number_of_millions)
68
+ groups = group_with_big_names(number_of_millions)
69
+ fail ArgumentError, 'Number too large' if groups.size > BIG.size
70
+
71
+ groups
72
+ .reject { |amount, *| amount.zero? }
73
+ .map { |amount, name| quantify_big_name(amount, name) }
74
+ .join(' ')
75
+ end
76
+
77
+ def quantify_big_name(amount, big_name)
78
+ if amount == 1
79
+ quantity = 'eine'
80
+ else
81
+ quantity = convert(amount)
82
+ big_name = big_name.sub(/(e?)$/, 'en')
83
+ end
84
+
85
+ "#{quantity} #{big_name}"
86
+ end
87
+
88
+ # 12345678 => [[12, "Billion"], [345, "Milliarde"], [678, "Million"]]
89
+ def group_with_big_names(number_of_millions)
90
+ groups = []
91
+
92
+ until number_of_millions.zero?
93
+ number_of_millions, last_3 = number_of_millions.divmod(1000)
94
+ groups << last_3
95
+ end
96
+
97
+ groups.zip(BIG).reverse
98
+ end
99
+
100
+ def convert_decimals(number)
101
+ decimals = get_decimals_as_string(number)
102
+ return '' if decimals.empty?
103
+
104
+ ' Komma ' + convert_digits(decimals)
105
+ end
106
+
107
+ def get_decimals_as_string(number)
108
+ number.to_s[/\.(\d+)/, 1].to_s
109
+ end
110
+
111
+ def convert_digits(number)
112
+ number.to_s.chars.map { |digit| convert_integer(digit) }.join(' ')
113
+ end
114
+
115
+ end
data/ziffern_spec.rb ADDED
@@ -0,0 +1,89 @@
1
+ require './ziffern'
2
+
3
+ describe Ziffern do
4
+
5
+ subject { Ziffern.new }
6
+
7
+ def self.test_german_numbers(hash)
8
+ hash.each do |integer, german|
9
+ instance_eval do
10
+ it "converts #{integer} to #{german}" do
11
+ expect(subject.to_german(integer)).to eq german
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ context 'numbers up to 20' do
18
+ test_german_numbers({
19
+ 0 => "null",
20
+ 1 => "eins",
21
+ 13 => "dreizehn",
22
+ 19 => "neunzehn",
23
+ })
24
+ end
25
+
26
+ context 'numbers up to 100' do
27
+ test_german_numbers({
28
+ 20 => "zwanzig",
29
+ 21 => "einundzwanzig",
30
+ 63 => "dreiundsechzig",
31
+ 99 => "neunundneunzig",
32
+ })
33
+ end
34
+
35
+ context 'numbers up to 1000' do
36
+ test_german_numbers({
37
+ 100 => "einhundert",
38
+ 234 => "zweihundertvierunddreißig",
39
+ 999 => "neunhundertneunundneunzig",
40
+ })
41
+ end
42
+
43
+ context 'up to one million' do
44
+ test_german_numbers({
45
+ 1000 => "eintausend",
46
+ 1234 => "eintausendzweihundertvierunddreißig",
47
+ 10_000 => "zehntausend",
48
+ 999_999 => "neunhundertneunundneunzigtausendneunhundertneunundneunzig",
49
+ })
50
+ end
51
+
52
+ context 'really big numbers' do
53
+ test_german_numbers({
54
+ 1_000_000 => "eine Million",
55
+ 1_000_001 => "eine Million eins",
56
+ 2_204_510 => "zwei Millionen zweihundertviertausendfünfhundertzehn",
57
+ 1_203_400_021 => "eine Milliarde zweihundertdrei Millionen vierhunderttausendeinundzwanzig",
58
+ 3_000_000_000_000_099 => "drei Billiarden neunundneunzig",
59
+ 10 ** 123 => "eine Vigintilliarde"
60
+ })
61
+ end
62
+
63
+ it 'throws an ArgumentError if the number is bigger than it can handle' do
64
+ expect { subject.to_german(10 ** 126) }.to raise_error ArgumentError
65
+ end
66
+
67
+ context 'negative numbers' do
68
+ test_german_numbers({
69
+ -1 => "minus eins",
70
+ -20 => "minus zwanzig",
71
+ -21 => "minus einundzwanzig",
72
+ -63 => "minus dreiundsechzig",
73
+ -99 => "minus neunundneunzig",
74
+ })
75
+ end
76
+
77
+
78
+ context 'decimals' do
79
+ test_german_numbers({
80
+ 0.1234 => "null Komma eins zwei drei vier",
81
+ 5.6789 => "fünf Komma sechs sieben acht neun",
82
+ -5.6 => "minus fünf Komma sechs",
83
+ -567.89 => "minus fünfhundertsiebenundsechzig Komma acht neun",
84
+ 5.0 => "fünf Komma null",
85
+ '5.00' => "fünf Komma null null"
86
+ })
87
+ end
88
+
89
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ziffern
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jimmy Börjesson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description:
56
+ email: lagginglion@gmail.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - README.md
62
+ - ziffern.rb
63
+ - ziffern_spec.rb
64
+ homepage: https://github.com/alcesleo/ziffern
65
+ licenses:
66
+ - MIT
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - "."
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 2.2.2
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Converts numbers to text, in German.
88
+ test_files:
89
+ - ziffern_spec.rb