trusted-number 0.2.0 → 0.3.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: de7c65f813fed797bf85b4cf8ea88ff2dda8b46fee5c80d3dc5805fbf3bddf0c
4
- data.tar.gz: 32db486cbc0acf549e41f72c690b25f47f0d586a0b29eb62ce0756251e7f7c59
3
+ metadata.gz: f83f617f7f38adb5933a47ffa20bab82ca3c607f9fc23e47adbf6b9d72c9d2fe
4
+ data.tar.gz: 8c4723d5651ce2060abacf790649e5e3e9acc804887dff4f08cfd672b86aa8bb
5
5
  SHA512:
6
- metadata.gz: bda7066152658490ff0293b2da171f1f95e7a81f4061e2c172a0edfd7ae026cf295a707ede6c89ada9c1a4ca28884159cfc7ca45c781ee75dc3e9eb458e26d4c
7
- data.tar.gz: f9c4be735a77a14073674059e289ce9410301f5cb2f86d61d4789e5901642f41af97018d7cc5b493da0762f975b32a261adc28324bf5ad85ba677a5bbf141efe
6
+ metadata.gz: 06af918dc5031bbdd61aae17e644c80fdac2c608fba850c69a6145526251f7acc9eca015e151ac0c485f82bb33a1ac10b9fb9b6eb5b9c99eb2497580dc31aed8
7
+ data.tar.gz: 4e4f4c8dac3fdadb1dac65ade3a2db49ba8bae1c21eb68e355131d01b54e908dfc06bc37c4cf4081aded70d502eb03c65dd14e0a14e81897445fbfb53e46c444
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2026-04-02
4
+
5
+ - Add `TNumber` as alias of `TrustedNumber` class
6
+ - Add factory `TrustedNumber.factory(base)`
7
+ - Add more tests
8
+ - Add documentation
9
+
3
10
  ## [0.1.1] - 2026-03-31
4
11
 
5
12
  - Add MPL 2.0 license
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  A trusted number is a number whose value will not change secretly.
4
4
 
5
+ For example (with base 10 numbers): `0.1 + 0.2 == 0.3`.
6
+
5
7
  ## Installation
6
8
 
7
9
  ```bash
@@ -10,17 +12,38 @@ gem install trusted-number
10
12
 
11
13
  ## Usage
12
14
 
13
- TODO: Write usage instructions here
15
+ Example (base 10):
16
+
17
+ ```ruby
18
+ require "trusted-number"
19
+
20
+ dec1 = TrustedNumber.new("0.1")
21
+ dec2 = TrustedNumber.new("0.2")
22
+
23
+ print " Base 10: 0.1 + 0.2 == "
24
+ puts dec1 + dec2 #=> 0.3
25
+ ```
26
+
27
+ Example (base 2):
28
+
29
+ ```ruby
30
+ bin1 = TrustedNumber.new("101.1", base: 2)
31
+ bin2 = TrustedNumber.new("0.1", base: 2)
32
+
33
+ print " Base 2: 101.1 + 0.1 == "
34
+ puts bin1 + bin2 #=> 110(b2)
35
+ ```
14
36
 
15
- ## Development
37
+ > More [examples](./examples/)
16
38
 
17
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
39
+ ## Contents
18
40
 
19
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
41
+ * [Create numbers](./docs/create.md)
42
+ * [Use numbers](./docs/use.md)
43
+ * [Available operations](./docs/operations.md)
44
+ * [Development](./docs/development.md)
20
45
 
21
46
  ## Contributing
22
47
 
23
48
  Bug reports and pull requests are welcome on GitHub at https://github.com/dvarrui/trusted-number.
24
49
 
25
- ---
26
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/trusted/number`. To experiment with that code, run `bin/console` for an interactive prompt.
data/Rakefile CHANGED
@@ -12,3 +12,15 @@ end
12
12
  require "standard/rake"
13
13
 
14
14
  task default: %i[test standard]
15
+
16
+ # Custom tasks
17
+
18
+ desc "Help"
19
+ task :help do
20
+ system("rake -T")
21
+ end
22
+
23
+ desc "Run standard:fix"
24
+ task :sf do
25
+ system("rake standard:fix")
26
+ end
data/docs/create.md ADDED
@@ -0,0 +1,46 @@
1
+ [<< back](../README.md)
2
+
3
+ # Create
4
+
5
+ ## 1. Create TrustedNumber numbers
6
+
7
+ 1. Load `trusted-number` library.
8
+ 2. Create `TrustedNumber` number objects. Base 10 by default.
9
+ 3. Operate with numbers.
10
+
11
+ ```ruby
12
+ require "trusted-number"
13
+
14
+ num1 = TrustedNumber.new("0.1")
15
+ num2 = TrustedNumber.new("0.2")
16
+
17
+ puts num1 + num2
18
+ ```
19
+
20
+ ## 2. TrustedNumber constructor options
21
+
22
+ > **NOTE**: For now, it is only possible to perform operations between numbers with the same base.
23
+
24
+ ```ruby
25
+ require_relative "trusted-number"
26
+
27
+ dec1 = TrustedNumber.new("3.14")
28
+ bin2 = TrustedNumber.new("101", base: 2)
29
+ hex3 = TrustedNumber.new("FF", base: 16)
30
+ ```
31
+
32
+ ## 3. Alias TNumber
33
+
34
+ The alias is a shorthand way of referring to the main class.
35
+
36
+ ```ruby
37
+ require "trusted-number"
38
+
39
+ num1 = TNumber.new("0.1")
40
+ num2 = TNumber.new("0.2")
41
+
42
+ puts num1 + num2
43
+ ```
44
+
45
+ ## 4. Factory
46
+
@@ -0,0 +1,10 @@
1
+ [<< back](../README.md)
2
+
3
+ ## Development
4
+
5
+ In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Ruby code in the file `lib/trusted-number`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
8
+
9
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
10
+
@@ -0,0 +1,9 @@
1
+ [<< back](../README.md)
2
+
3
+ # Operations
4
+
5
+ > **NOTE**: For now, it is only possible to perform operations between numbers with the same base.
6
+
7
+ * Create number object using bases from 2 to 23.
8
+ * Compare (`==`, `<`, `>`)
9
+ * Add (`+`)
data/docs/use.md ADDED
@@ -0,0 +1,29 @@
1
+ [<< back](../README.md)
2
+
3
+ # Use numbers
4
+
5
+ 1. Load `trusted-number` library.
6
+ 2. Create `TrustedNumber` number. Base 10 by default.
7
+ 3. Operate with numbers.
8
+
9
+ ## Sum numbers
10
+
11
+ ```ruby
12
+ require "trusted-number"
13
+
14
+ num1 = TrustedNumber.new("0.1")
15
+ num2 = TrustedNumber.new("0.2")
16
+
17
+ puts num1 + num2
18
+ ```
19
+
20
+ ## Compare numbers
21
+
22
+ ```ruby
23
+ num1 = TrustedNumber.new("-1,5")
24
+ num2 = TrustedNumber.new("2")
25
+
26
+ puts (num1 == num2) #=> false
27
+ puts (num1 < num2) #=> true
28
+ puts (num1 > num2) #=> false
29
+ ```
data/examples/add.rb ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative "../lib/trusted-number"
3
+ require_relative "line"
4
+
5
+ line
6
+ puts "Example : 101.1 + 0.1 (base 2)"
7
+
8
+ bin1 = TrustedNumber.new("101.1", base: 2)
9
+ bin2 = TrustedNumber.new("0.1", base: 2)
10
+
11
+ res = bin1 + bin2
12
+ puts "Result : #{res.value}"
13
+ puts res.about
14
+
15
+ line
16
+ puts "Example : 0.1 + 0.2 (base 10)"
17
+ dec1 = TrustedNumber.new("0.1")
18
+ dec2 = TrustedNumber.new("0.2")
19
+
20
+ res = dec1 + dec2
21
+ puts "Result : #{res.value}"
22
+ puts res.about
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative "../lib/trusted-number"
3
+
4
+ def line
5
+ puts "\n" + "-" * 40
6
+ end
7
+
8
+ num1 = TrustedNumber.new("0")
9
+ num2 = TrustedNumber.new("-0.2")
10
+ num3 = TrustedNumber.new("-3.0")
11
+ num4 = TrustedNumber.new("4.5")
12
+
13
+ line
14
+ puts "Example:"
15
+ puts "- #{num1.value} == #{num2.value} => #{num1 == num2}"
16
+ puts "- #{num1.value} > #{num2.value} => #{num1 > num2}"
17
+ puts "- #{num1.value} < #{num2.value} => #{num1 < num2}"
18
+
19
+ line
20
+ puts "Example:"
21
+ puts "- #{num2.value} == #{num3.value} => #{num2 == num3}"
22
+ puts "- #{num2.value} > #{num3.value} => #{num2 > num3}"
23
+ puts "- #{num2.value} < #{num3.value} => #{num2 < num3}"
24
+
25
+ line
26
+ puts "Example:"
27
+ puts "- #{num4.value} == #{num3.value} => #{num4 == num3}"
28
+ puts "- #{num4.value} > #{num3.value} => #{num4 > num3}"
29
+ puts "- #{num4.value} < #{num3.value} => #{num4 < num3}"
data/examples/line.rb ADDED
@@ -0,0 +1,3 @@
1
+ def line
2
+ puts "\n" + "-" * 40
3
+ end
data/examples/new.rb ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative "../lib/trusted-number"
3
+ require "debug"
4
+
5
+ def line
6
+ puts "\n" + "-" * 40
7
+ end
8
+
9
+ num = TrustedNumber.new("123.456")
10
+
11
+ line
12
+ puts "Example: 123.456"
13
+ puts "- base : #{num.base}"
14
+ puts "- sign : #{num.sign}"
15
+ puts "- predot : #{num.predot}"
16
+ puts "- postdot : #{num.postdot}"
17
+ puts "- value : #{num.value}"
18
+ puts "- about : #{num.about}"
data/examples/use.rb ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative "../lib/trusted-number"
3
+ require_relative "line"
4
+
5
+ line
6
+ num1 = TrustedNumber.new("0.1")
7
+ num2 = TrustedNumber.new("0.2")
8
+ print "Example (base #{num1.base}): #{num1.value} + #{num2.value} == "
9
+ puts num1 + num2
10
+
11
+ line
12
+ num1 = TrustedNumber.new("101.1", base: 2)
13
+ num2 = TrustedNumber.new("0.1", base: 2)
14
+ print "Example (base #{num1.base}): #{num1.value} + #{num2.value} == "
15
+ puts num1 + num2
16
+
17
+ line
18
+ num1 = TNumber.new(3.1415)
19
+ num2 = TNumber.new(10)
20
+ print "Example (base #{num1.base}): #{num1.value} + #{num2.value} == "
21
+ puts num1 + num2
22
+
23
+ line
24
+ num1 = TNumber.new("af", base: 16)
25
+ num2 = TNumber.new(2, base: 16)
26
+ print "Example (base #{num1.base}): #{num1.value} + #{num2.value} == "
27
+ puts num1 + num2
@@ -5,15 +5,15 @@ class TrustedNumber
5
5
  p1 = @postdot.ljust(max_post, "0")
6
6
  p2 = other.postdot.ljust(max_post, "0")
7
7
 
8
- # Sum postdot
9
8
  res_post, carry = add_strings(p1, p2, @base)
10
9
 
11
10
  # Sum predot + carry
12
11
  res_pre, final_carry = add_strings(@predot, other.predot, @base, carry)
13
12
  res_pre = DIGITS[final_carry] + res_pre if final_carry > 0
14
13
 
15
- build_result(res_pre, res_post)
14
+ create_new_tnumber(res_pre, res_post)
16
15
  end
16
+ alias_method :add, :+
17
17
 
18
18
  private
19
19
 
@@ -0,0 +1,39 @@
1
+ class TrustedNumber
2
+ include Comparable
3
+
4
+ def ==(other)
5
+ cond = (@base == other.base)
6
+ cond &&= (@predot == other.predot)
7
+ cond &&= (@postdot == other.postdot)
8
+
9
+ cond
10
+ end
11
+ alias_method :equal?, :==
12
+ alias_method :eq?, :==
13
+
14
+ def <=>(other)
15
+ return nil unless other.is_a?(TrustedNumber)
16
+ return 0 if about == other.about
17
+
18
+ # compare sign
19
+ return 1 if positive? && other.negative?
20
+ return -1 if negative? && other.positive?
21
+
22
+ # compare predot
23
+ max_pre = [@predot.length, other.predot.length].max
24
+ s1_pre = @predot.rjust(max_pre, "0")
25
+ s2_pre = other.predot.rjust(max_pre, "0")
26
+
27
+ return s1_pre <=> s2_pre if s1_pre != s2_pre
28
+
29
+ # compare postdot
30
+ max_post = [@postdot.length, other.postdot.length].max
31
+ s1_post = @postdot.ljust(max_post, "0")
32
+ s2_post = other.postdot.ljust(max_post, "0")
33
+
34
+ s1_post <=> s2_post
35
+ end
36
+
37
+ alias_method :lt?, :<
38
+ alias_method :gt?, :>
39
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class TrustedNumber
2
4
  def *(other)
3
5
  # Algoritmo: Multiplicar como si no hubiera puntos, luego posicionar punto
@@ -1,29 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class TrustedNumber
2
4
  def -(other)
3
- # 1. Alinear decimales
4
- max_post = [@postnumber.length, other.postnumber.length].max
5
- p1 = @postnumber.ljust(max_post, "0")
6
- p2 = other.postnumber.ljust(max_post, "0")
5
+ # align post
6
+ max_post = [@postdot.length, other.postdot.length].max
7
+ p1 = @postdot.ljust(max_post, ZERO)
8
+ p2 = other.postdot.ljust(max_post, ZERO)
7
9
 
8
- # 2. Restar postnumbers (manejando el "pedir prestado" o borrow)
9
- res_post, borrow = sub_strings(p1, p2, @base)
10
+ res_post, borrow = subtract_strings(p1, p2, @base)
10
11
 
11
12
  # 3. Restar prenumbers - borrow
12
13
  res_pre, _ = sub_strings(@prenumber, other.prenumber, @base, borrow)
13
14
 
14
- build_result(res_pre, res_post)
15
+ create_new_tnumber(res_pre, res_post)
15
16
  end
17
+ alias_method :subtract, :-
16
18
 
17
19
  private
18
20
 
19
- def sub_strings(s1, s2, base, borrow = 0)
21
+ def subtract_strings(s1, s2, base, borrow = 0)
20
22
  res = ""
21
23
  i, j = s1.length - 1, s2.length - 1
22
24
  while i >= 0 || j >= 0
23
25
  v1 = (i >= 0) ? DIGITS.index(s1[i]) : 0
24
26
  v2 = ((j >= 0) ? DIGITS.index(s2[j]) : 0) + borrow
25
27
  if v1 < v2
26
- v1 += base
28
+ v1 += @base
27
29
  borrow = 1
28
30
  else
29
31
  borrow = 0
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class TrustedNumber
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -1,57 +1,113 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "trusted-number/version"
4
3
  require_relative "trusted-number/add"
5
- require_relative "trusted-number/equal"
6
- require_relative "trusted-number/sub"
4
+ require_relative "trusted-number/compare"
7
5
  require_relative "trusted-number/mul"
6
+ require_relative "trusted-number/subtract"
7
+ require_relative "trusted-number/version"
8
8
 
9
9
  class TrustedNumber
10
- attr_reader :base
11
- attr_reader :predot, :postdot
10
+ attr_reader :base, :sign, :predot, :postdot
12
11
 
13
12
  DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz"
14
13
  ZERO = "0"
15
14
  DOT = "."
15
+ POSITIVE = "+"
16
+ NEGATIVE = "-"
17
+
18
+ def self.factory(base)
19
+ unless base == base.to_i || base < 1
20
+ raise ArgumentError, "Invalid base (Natural number > 1)"
21
+ end
22
+
23
+ ->(number) { new(number, base: base) }
24
+ end
16
25
 
17
26
  def initialize(number, base: 10)
18
- @number = number
27
+ @number = number.to_s.strip
19
28
  @base = base
20
29
 
21
- num_str = @number.to_s.downcase.delete(" ")
22
- pre, post = num_str.split(DOT)
23
- @predot = pre || ZERO
24
- @postdot = post || ZERO
30
+ fill_attibutes(@number)
31
+ validate_format
32
+ end
25
33
 
26
- validate_format!
34
+ def about
35
+ "TrustedNumber: #{value}|base:#{@base}|sign:#{@sign}|pre:#{@predot}|post:#{@postdot}"
27
36
  end
28
37
 
29
- def value
30
- return @predot if @postdot == ZERO
38
+ def negative?
39
+ @sign == NEGATIVE
40
+ end
31
41
 
32
- "#{@predot}#{DOT}#{@postdot}"
42
+ def positive?
43
+ !negative?
33
44
  end
34
45
 
35
46
  def to_s
36
- "TrustedNumber: #{value} (base: #{@base})"
47
+ value
48
+ end
49
+
50
+ def value
51
+ sign = (@sign == POSITIVE) ? "" : @sign
52
+
53
+ number = if @postdot == ZERO
54
+ @predot
55
+ else
56
+ "#{@predot}#{DOT}#{@postdot}"
57
+ end
58
+ base = "(b#{@base})"
59
+ base = "" if @base == 10
60
+ "#{sign}#{number.upcase}#{base}"
37
61
  end
38
62
 
39
63
  private
40
64
 
41
- def build_result(pre, post)
65
+ def create_new_tnumber(pre, post)
42
66
  pre_clean = pre.gsub(/^0+(?=\d)/, "")
43
67
  pre_clean = ZERO if pre_clean.empty?
44
68
 
45
69
  post_clean = post.gsub(/0+$/, "")
46
- str = post_clean.empty? ? pre_clean : "#{pre_clean}.#{post_clean}"
47
- TrustedNumber.new(str, base: @base)
70
+ str_number = post_clean.empty? ? pre_clean : "#{pre_clean}.#{post_clean}"
71
+ TrustedNumber.new(str_number, base: @base)
48
72
  end
49
73
 
50
- def validate_format!
74
+ def fill_attibutes(number)
75
+ num_str = number.to_s.downcase.delete(" ")
76
+ num_str = fill_sign(num_str)
77
+
78
+ pre, post = num_str.split(DOT)
79
+
80
+ pre&.gsub!(/\A0+/, "")
81
+ @predot = if pre.nil? || pre == ""
82
+ ZERO
83
+ else
84
+ pre
85
+ end
86
+
87
+ post&.sub!(/0+\z/, "")
88
+ @postdot = if post.nil? || post == ""
89
+ ZERO
90
+ else
91
+ post
92
+ end
93
+ end
94
+
95
+ def fill_sign(number)
96
+ @sign = POSITIVE
97
+ if number.start_with?(NEGATIVE)
98
+ @sign = NEGATIVE
99
+ number = number[1..]
100
+ end
101
+ number
102
+ end
103
+
104
+ def validate_format
51
105
  allowed = DIGITS[0...@base]
52
106
  pattern = /\A[#{allowed}]*\z/
53
107
  unless @predot.match?(pattern) && @postdot.match?(pattern)
54
- raise ArgumentError, "Caracteres inválidos para base #{@base}"
108
+ raise ArgumentError, "Invalid chars (base #{@base})"
55
109
  end
56
110
  end
57
111
  end
112
+
113
+ TNumber = TrustedNumber
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trusted-number
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Vargas
@@ -20,12 +20,20 @@ files:
20
20
  - LICENSE
21
21
  - README.md
22
22
  - Rakefile
23
- - examples/01-add.rb
23
+ - docs/create.md
24
+ - docs/development.md
25
+ - docs/operations.md
26
+ - docs/use.md
27
+ - examples/add.rb
28
+ - examples/compare.rb
29
+ - examples/line.rb
30
+ - examples/new.rb
31
+ - examples/use.rb
24
32
  - lib/trusted-number.rb
25
33
  - lib/trusted-number/add.rb
26
- - lib/trusted-number/equal.rb
34
+ - lib/trusted-number/compare.rb
27
35
  - lib/trusted-number/mul.rb
28
- - lib/trusted-number/sub.rb
36
+ - lib/trusted-number/subtract.rb
29
37
  - lib/trusted-number/version.rb
30
38
  - sig/trusted-number.rbs
31
39
  homepage: https://github.com/dvarrui/trusted-number
data/examples/01-add.rb DELETED
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require_relative "../lib/trusted-number"
3
-
4
- # ------------
5
- puts "\n" + "=" * 10
6
- puts "Base 2:"
7
-
8
- bin1 = TrustedNumber.new("1.1", base: 2) # (1.5 decimal)
9
- bin2 = TrustedNumber.new("1.1", base: 2) # (1.5 decimal)
10
-
11
- res = bin1 + bin2
12
- puts res
13
- puts "Value: #{res.value}" # => "11" (3.0 en decimal)
14
-
15
- # ------------
16
- puts "\n" + "=" * 10
17
- puts "Base 10"
18
- dec1 = TrustedNumber.new("0.1")
19
- dec2 = TrustedNumber.new("0.2")
20
-
21
- res = dec1 + dec2
22
- puts res
23
- puts "Value: #{res.value}"
@@ -1,9 +0,0 @@
1
- class TrustedNumber
2
- def ==(other)
3
- cond = (@base == other.base)
4
- cond &&= (@predot = other.predot)
5
- cond &&= (@posdot = other.postdot)
6
-
7
- cond
8
- end
9
- end