trusted-number 0.1.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 +7 -0
- data/CHANGELOG.md +5 -0
- data/README.md +26 -0
- data/Rakefile +14 -0
- data/examples/demo.rb +23 -0
- data/lib/trusted-number/add.rb +34 -0
- data/lib/trusted-number/equal.rb +9 -0
- data/lib/trusted-number/mul.rb +42 -0
- data/lib/trusted-number/sub.rb +37 -0
- data/lib/trusted-number/version.rb +5 -0
- data/lib/trusted-number.rb +51 -0
- data/sig/trusted-number.rbs +5 -0
- metadata +53 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d654dde743a279a169c51a99e165c81e6b752fba76e0a7e809cb70d6ded6a9f4
|
|
4
|
+
data.tar.gz: 816e752739bc7c0752bc2c58059e6406c6cc4fb960049dc13735fb93116bdddb
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d75a97abd836092f32de8848ab222fdcb3047e44d9d84de6547d809e1ad0073534a2a1056efbe8ed6f410ad30503c6e55f97fd799f3eebf53c92339d5513d2a7
|
|
7
|
+
data.tar.gz: 5910305e64fc6de7ef1ac80ff6fee7fb6a386b0183b1cc1d5706c8133b37e641922e07602818adba9e7a612d64342b11a4793d43108344fd7e1082cf6927e4a7
|
data/CHANGELOG.md
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# trusted-number
|
|
2
|
+
|
|
3
|
+
A trusted number is a number whose value will not change secretly.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
gem install trusted-number
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
TODO: Write usage instructions here
|
|
14
|
+
|
|
15
|
+
## Development
|
|
16
|
+
|
|
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.
|
|
18
|
+
|
|
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).
|
|
20
|
+
|
|
21
|
+
## Contributing
|
|
22
|
+
|
|
23
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/dvarrui/trusted-number.
|
|
24
|
+
|
|
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
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "rake/testtask"
|
|
5
|
+
|
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
|
7
|
+
t.libs << "test"
|
|
8
|
+
t.libs << "lib"
|
|
9
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
require "standard/rake"
|
|
13
|
+
|
|
14
|
+
task default: %i[test standard]
|
data/examples/demo.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
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}"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class TrustedNumber
|
|
2
|
+
def +(other)
|
|
3
|
+
# 1. Alinear partes decimales (rellenar con 0 a la derecha)
|
|
4
|
+
max_post = [@postnumber.length, other.postnumber.length].max
|
|
5
|
+
p1 = @postnumber.ljust(max_post, "0")
|
|
6
|
+
p2 = other.postnumber.ljust(max_post, "0")
|
|
7
|
+
|
|
8
|
+
# 2. Sumar postnumbers
|
|
9
|
+
res_post, carry = add_strings(p1, p2, @base)
|
|
10
|
+
|
|
11
|
+
# 3. Sumar prenumbers + acarreo anterior
|
|
12
|
+
res_pre, final_carry = add_strings(@prenumber, other.prenumber, @base, carry)
|
|
13
|
+
res_pre = DIGITS[final_carry] + res_pre if final_carry > 0
|
|
14
|
+
|
|
15
|
+
build_result(res_pre, res_post)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def add_strings(s1, s2, base, carry = 0)
|
|
21
|
+
res = []
|
|
22
|
+
i, j = s1.length - 1, s2.length - 1
|
|
23
|
+
while i >= 0 || j >= 0
|
|
24
|
+
v1 = (i >= 0) ? DIGITS.index(s1[i]) : 0
|
|
25
|
+
v2 = (j >= 0) ? DIGITS.index(s2[j]) : 0
|
|
26
|
+
sum = v1 + v2 + carry
|
|
27
|
+
res << DIGITS[sum % base]
|
|
28
|
+
carry = sum / base
|
|
29
|
+
i -= 1
|
|
30
|
+
j -= 1
|
|
31
|
+
end
|
|
32
|
+
[res.reverse.join, carry]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
class TrustedNumber
|
|
2
|
+
def *(other)
|
|
3
|
+
# Algoritmo: Multiplicar como si no hubiera puntos, luego posicionar punto
|
|
4
|
+
s1 = @prenumber + @postnumber
|
|
5
|
+
s2 = other.prenumber + other.postnumber
|
|
6
|
+
|
|
7
|
+
# Multiplicación de strings (suma de productos parciales)
|
|
8
|
+
res_int = multiply_strings(s1, s2, @base)
|
|
9
|
+
|
|
10
|
+
# Posicionar el punto decimal
|
|
11
|
+
total_decimals = @postnumber.length + other.postnumber.length
|
|
12
|
+
|
|
13
|
+
if total_decimals > 0
|
|
14
|
+
# Asegurar que el string sea lo bastante largo
|
|
15
|
+
res_int = res_int.rjust(total_decimals + 1, "0")
|
|
16
|
+
new_pre = res_int[0...-total_decimals]
|
|
17
|
+
# new_post = res_int[-total_decimals..-1]
|
|
18
|
+
new_post = res_int[-total_decimals..]
|
|
19
|
+
else
|
|
20
|
+
new_pre, new_post = res_int, ""
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
build_result(new_pre, new_post)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def multiply_strings(s1, s2, base)
|
|
29
|
+
# Multiplicación básica (Long Multiplication) carácter a carácter
|
|
30
|
+
product = Array.new(s1.length + s2.length, 0)
|
|
31
|
+
|
|
32
|
+
(s1.length - 1).downto(0) do |i|
|
|
33
|
+
(s2.length - 1).downto(0) do |j|
|
|
34
|
+
mul = DIGITS.index(s1[i]) * DIGITS.index(s2[j])
|
|
35
|
+
sum = mul + product[i + j + 1]
|
|
36
|
+
product[i + j + 1] = sum % base
|
|
37
|
+
product[i + j] += sum / base
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
product.map { |d| DIGITS[d] }.join.gsub(/^0+(?=\d)/, "")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
class TrustedNumber
|
|
2
|
+
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")
|
|
7
|
+
|
|
8
|
+
# 2. Restar postnumbers (manejando el "pedir prestado" o borrow)
|
|
9
|
+
res_post, borrow = sub_strings(p1, p2, @base)
|
|
10
|
+
|
|
11
|
+
# 3. Restar prenumbers - borrow
|
|
12
|
+
res_pre, _ = sub_strings(@prenumber, other.prenumber, @base, borrow)
|
|
13
|
+
|
|
14
|
+
build_result(res_pre, res_post)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def sub_strings(s1, s2, base, borrow = 0)
|
|
20
|
+
res = ""
|
|
21
|
+
i, j = s1.length - 1, s2.length - 1
|
|
22
|
+
while i >= 0 || j >= 0
|
|
23
|
+
v1 = (i >= 0) ? DIGITS.index(s1[i]) : 0
|
|
24
|
+
v2 = ((j >= 0) ? DIGITS.index(s2[j]) : 0) + borrow
|
|
25
|
+
if v1 < v2
|
|
26
|
+
v1 += base
|
|
27
|
+
borrow = 1
|
|
28
|
+
else
|
|
29
|
+
borrow = 0
|
|
30
|
+
end
|
|
31
|
+
res << DIGITS[v1 - v2]
|
|
32
|
+
i -= 1
|
|
33
|
+
j -= 1
|
|
34
|
+
end
|
|
35
|
+
[res.reverse, borrow]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "trusted-number/version"
|
|
4
|
+
require_relative "trusted-number/add"
|
|
5
|
+
require_relative "trusted-number/equal"
|
|
6
|
+
require_relative "trusted-number/sub"
|
|
7
|
+
require_relative "trusted-number/mul"
|
|
8
|
+
|
|
9
|
+
class TrustedNumber
|
|
10
|
+
attr_reader :base
|
|
11
|
+
attr_reader :prenumber, :postnumber
|
|
12
|
+
|
|
13
|
+
DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz"
|
|
14
|
+
|
|
15
|
+
def initialize(number, base: 10)
|
|
16
|
+
@number = number
|
|
17
|
+
@base = base
|
|
18
|
+
|
|
19
|
+
num_str = @number.to_s.downcase.delete(" ")
|
|
20
|
+
pre, post = num_str.split(".")
|
|
21
|
+
@prenumber = pre || "0"
|
|
22
|
+
@postnumber = post || ""
|
|
23
|
+
|
|
24
|
+
validate_format!
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def value
|
|
28
|
+
@postnumber.empty? ? @prenumber : "#{@prenumber}.#{@postnumber}"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_s
|
|
32
|
+
"TrustedNumber: #{value} (base: #{@base})"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def build_result(pre, post)
|
|
38
|
+
pre_clean = pre.gsub(/^0+(?=\d)/, "")
|
|
39
|
+
post_clean = post.gsub(/0+$/, "")
|
|
40
|
+
str = post_clean.empty? ? pre_clean : "#{pre_clean}.#{post_clean}"
|
|
41
|
+
TrustedNumber.new(str, base: @base)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def validate_format!
|
|
45
|
+
allowed = DIGITS[0...@base]
|
|
46
|
+
pattern = /\A[#{allowed}]*\z/
|
|
47
|
+
unless @prenumber.match?(pattern) && @postnumber.match?(pattern)
|
|
48
|
+
raise ArgumentError, "Caracteres inválidos para base #{@base}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: trusted-number
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- David Vargas
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: A trusted number is a number whose value will not change secretly.
|
|
13
|
+
email:
|
|
14
|
+
- dvarrui@proton.me
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- CHANGELOG.md
|
|
20
|
+
- README.md
|
|
21
|
+
- Rakefile
|
|
22
|
+
- examples/demo.rb
|
|
23
|
+
- lib/trusted-number.rb
|
|
24
|
+
- lib/trusted-number/add.rb
|
|
25
|
+
- lib/trusted-number/equal.rb
|
|
26
|
+
- lib/trusted-number/mul.rb
|
|
27
|
+
- lib/trusted-number/sub.rb
|
|
28
|
+
- lib/trusted-number/version.rb
|
|
29
|
+
- sig/trusted-number.rbs
|
|
30
|
+
homepage: https://github.com/dvarrui/trusted-number
|
|
31
|
+
licenses: []
|
|
32
|
+
metadata:
|
|
33
|
+
homepage_uri: https://github.com/dvarrui/trusted-number
|
|
34
|
+
source_code_uri: https://github.com/dvarrui/trusted-number
|
|
35
|
+
changelog_uri: https://github.com/dvarrui/trusted-number/blob/main/CHANGELOG.md
|
|
36
|
+
rdoc_options: []
|
|
37
|
+
require_paths:
|
|
38
|
+
- lib
|
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
40
|
+
requirements:
|
|
41
|
+
- - ">="
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: 3.2.0
|
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '0'
|
|
49
|
+
requirements: []
|
|
50
|
+
rubygems_version: 3.7.2
|
|
51
|
+
specification_version: 4
|
|
52
|
+
summary: A trusted number is a number whose value will not change secretly.
|
|
53
|
+
test_files: []
|