diff --git a/src/arithmetic.jl b/src/arithmetic.jl index b23e6e2..1cebca7 100644 --- a/src/arithmetic.jl +++ b/src/arithmetic.jl @@ -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) + return y + x + else # x.q ≥ y.q + # a₁ * 10^q₁ + a₂ * 10^q₂ = + # (a₁ * 10^(q₁ - q₂) + a₂) * 10^q₂ + # ^^^^^^^^^^^^^^^^^ Integer because q₁ ≥ q₂ + q = x.q - y.q + c = (-1)^(x.s) * x.c * BigTen^q + (-1)^(y.s) * y.c + s = Int(signbit(c)) + return normalize(Decimal(s, abs(c), y.q)) + end end # Negation diff --git a/test/test_arithmetic.jl b/test/test_arithmetic.jl index e21e772..952088c 100644 --- a/test/test_arithmetic.jl +++ b/test/test_arithmetic.jl @@ -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