Skip to content

Commit

Permalink
Merge pull request #63 from barucden/fixadd
Browse files Browse the repository at this point in the history
Fix addition
  • Loading branch information
tinybike authored Oct 13, 2024
2 parents 44b6616 + 5f9c5b0 commit 0180ccc
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
18 changes: 13 additions & 5 deletions src/arithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@ Base.promote_rule(::Type{Decimal}, ::Type{<:Real}) = Decimal
Base.promote_rule(::Type{BigFloat}, ::Type{Decimal}) = Decimal
Base.promote_rule(::Type{BigInt}, ::Type{Decimal}) = Decimal

const BigTen = BigInt(10)

# Addition
# To add, convert both decimals to the same exponent.
# (If the exponents are different, use the smaller exponent
# to make sure we're adding integers.)
function +(x::Decimal, y::Decimal)
cx = (-1)^x.s * x.c * 10^max(x.q - y.q, 0)
cy = (-1)^y.s * y.c * 10^max(y.q - x.q, 0)
s = (abs(cx) > abs(cy)) ? x.s : y.s
c = BigInt(cx) + BigInt(cy)
normalize(Decimal(s, abs(c), min(x.q, y.q)))
if x.q < y.q
x, y = y, x
end
# Here: x.q ≥ y.q
# a₁ * 10^q₁ + a₂ * 10^q₂ =
# (a₁ * 10^(q₁ - q₂) + a₂) * 10^q₂
# ^^^^^^^^^^^^^^^^^ this is integer because q₁ ≥ q₂
q = x.q - y.q
c = (-1)^x.s * x.c * BigTen^q + (-1)^y.s * y.c
s = signbit(c)
return normalize(Decimal(s, abs(c), y.q))
end

# Negation
Expand Down
2 changes: 2 additions & 0 deletions test/test_arithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ using Test
@test Decimal.([0.1 0.2]) .+ [0.3 0.1] == Decimal.([0.4 0.3])
@test Decimal(2147483646) + Decimal(1) == Decimal(2147483647)
@test Decimal(1,3,-2) + parse(Decimal, "0.2523410412138103") == Decimal(0,2223410412138103,-16)

@test Decimal(0, 10000000000000000001, -19) + Decimal(0, 1, 0) == Decimal(0, 20000000000000000001, -19)
end

@testset "Subtraction" begin
Expand Down

0 comments on commit 0180ccc

Please sign in to comment.