|
|
@@ -0,0 +1,237 @@
|
|
|
+//
|
|
|
+// bigdecimal.t.h
|
|
|
+// bigdecimal
|
|
|
+//
|
|
|
+// Created by Sam Jaffe on 7/5/17.
|
|
|
+//
|
|
|
+
|
|
|
+#pragma once
|
|
|
+
|
|
|
+#include "bigdecimal.h"
|
|
|
+
|
|
|
+#include <cxxtest/TestSuite.h>
|
|
|
+
|
|
|
+class bigdecimal_TestSuite : public CxxTest::TestSuite {
|
|
|
+public:
|
|
|
+// void testConstructFromStringIsSameValueAsFromInt() {
|
|
|
+// using bi = math::bigdecimal;
|
|
|
+// TS_ASSERT_EQUALS(bi("1000000"), bi(1000000));
|
|
|
+// }
|
|
|
+//
|
|
|
+
|
|
|
+ void testConstructIntegerAsDecimal() {
|
|
|
+ using bd = math::bigdecimal;
|
|
|
+ TS_ASSERT_EQUALS(bd("1000.00").to_string(), "1000.00");
|
|
|
+ }
|
|
|
+
|
|
|
+ void testConstructDecimal() {
|
|
|
+ using bd = math::bigdecimal;
|
|
|
+ TS_ASSERT_EQUALS(bd("1000.10").to_string(), "1000.10");
|
|
|
+ TS_ASSERT_EQUALS(bd("1000.01").to_string(), "1000.01");
|
|
|
+ }
|
|
|
+
|
|
|
+ void testRescaleHigherAddsDigits() {
|
|
|
+ math::bigdecimal dec(100);
|
|
|
+ TS_ASSERT_EQUALS(dec.scale(), 0);
|
|
|
+ dec.rescale(2);
|
|
|
+ TS_ASSERT_EQUALS(dec.to_string(), "100.00");
|
|
|
+ }
|
|
|
+
|
|
|
+ void testRescaleLowerCanBeLossy() {
|
|
|
+ math::bigdecimal dec("100.10");
|
|
|
+ TS_ASSERT_EQUALS(dec.scale(), 2);
|
|
|
+ dec.rescale(0);
|
|
|
+ dec.rescale(2);
|
|
|
+ TS_ASSERT_EQUALS(dec.to_string(), "100.00");
|
|
|
+ }
|
|
|
+
|
|
|
+ void testConstructWithScaleEqualsWithout() {
|
|
|
+ math::bigdecimal scl(100, -2);
|
|
|
+ TS_ASSERT_EQUALS(scl.to_string(), "100");
|
|
|
+ }
|
|
|
+
|
|
|
+ void testAddTwoDecimalsSameScale() {
|
|
|
+ using bd = math::bigdecimal;
|
|
|
+ bd a("1000.10");
|
|
|
+ bd b("1000.01");
|
|
|
+ TS_ASSERT_EQUALS(a.scale(), b.scale());
|
|
|
+ TS_ASSERT_EQUALS((a+b).to_string(), "2000.11");
|
|
|
+ }
|
|
|
+
|
|
|
+ void testAddTwoDecimalsDifferentScalesUsesHigherScale() {
|
|
|
+ using bd = math::bigdecimal;
|
|
|
+ bd a("1000.10");
|
|
|
+ bd b("1000");
|
|
|
+ TS_ASSERT(a.scale() > b.scale());
|
|
|
+ TS_ASSERT_EQUALS((a+b).to_string(), "2000.10");
|
|
|
+ }
|
|
|
+
|
|
|
+ void testAddNumberWithInversePreservesScale() {
|
|
|
+ math::bigdecimal a("1.001");
|
|
|
+ TS_ASSERT_EQUALS((a+(-a)).to_string(), "0.000");
|
|
|
+ }
|
|
|
+
|
|
|
+ void testSubtractTwoDecimalsDifferentScalesUsesHigherScale() {
|
|
|
+ using bd = math::bigdecimal;
|
|
|
+ bd a("900.10");
|
|
|
+ bd b("1000");
|
|
|
+ TS_ASSERT(a.scale() > b.scale());
|
|
|
+ TS_ASSERT_EQUALS((a-b).to_string(), "-99.90");
|
|
|
+ TS_ASSERT_EQUALS((b-a).to_string(), "99.90");
|
|
|
+ }
|
|
|
+
|
|
|
+// void testAddPastBounds() {
|
|
|
+// math::bigdecimal bi{999999999ULL};
|
|
|
+// TS_ASSERT_EQUALS((bi+1).to_string(), "1000000000");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testAddReciprocalIsZero() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS((bi+(-bi)).to_string(), "0");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testAddNegativeLargerGivesNegative() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS((bi+(-1001)).to_string(), "-1");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testAddNegativeSmallerGivesPositive() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS((bi+(-999)).to_string(), "1");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testSubSelfIsZero() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS((bi-bi).to_string(), "0");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testNegativeMinusNegativeIncreateAbs() {
|
|
|
+// math::bigdecimal bi{-1000};
|
|
|
+// TS_ASSERT_EQUALS((bi-100).to_string(), "-1100");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testSubLargerGivesNegative() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS((bi-1001).to_string(), "-1");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testSubSmallerGivesPositive() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS((bi-999).to_string(), "1");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testSubUnderflowBorrows() {
|
|
|
+// math::bigdecimal bi{1000000000ULL};
|
|
|
+// TS_ASSERT_EQUALS((bi-1).to_string(), "999999999");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testMultiplyZeroReturnsZero() {
|
|
|
+// auto &ZERO = math::bigdecimal::ZERO;
|
|
|
+// math::bigdecimal bi{999999999ULL};
|
|
|
+// TS_ASSERT_EQUALS(bi*ZERO, ZERO);
|
|
|
+// TS_ASSERT_EQUALS(ZERO*bi, ZERO);
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testMultiplyOneReturnsValue() {
|
|
|
+// auto &ONE = math::bigdecimal::ONE;
|
|
|
+// math::bigdecimal bi{999999999ULL};
|
|
|
+// TS_ASSERT_EQUALS((bi*ONE).to_string(), "999999999");
|
|
|
+// TS_ASSERT_EQUALS((ONE*bi).to_string(), "999999999");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testMultiplyNegativeOneReturnsInverse() {
|
|
|
+// auto &NEGATIVE_ONE = math::bigdecimal::NEGATIVE_ONE;
|
|
|
+// math::bigdecimal bi{999999999ULL};
|
|
|
+// TS_ASSERT_EQUALS((bi*NEGATIVE_ONE).to_string(), "-999999999");
|
|
|
+// TS_ASSERT_EQUALS((NEGATIVE_ONE*bi).to_string(), "-999999999");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testMultiplyOverflowsIntoNextCell() {
|
|
|
+// math::bigdecimal bi{999999999ULL};
|
|
|
+// TS_ASSERT_EQUALS((bi*bi).to_string(), "999999998000000001");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testMultiplyCarryIntoNextCell() {
|
|
|
+// math::bigdecimal bi{999999999ULL};
|
|
|
+// math::bigdecimal big{bi*bi};
|
|
|
+// TS_ASSERT_EQUALS((big*big).to_string(),
|
|
|
+// "999999996000000005999999996000000001");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testMultiplyNoOverflow() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS((bi*bi).to_string(), "1000000");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testDivideByZeroThrows() {
|
|
|
+// auto &ZERO = math::bigdecimal::ZERO;
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_THROWS(bi/ZERO, std::domain_error);
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testDivideByOneReturnsValue() {
|
|
|
+// auto &ONE = math::bigdecimal::ONE;
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS(bi/ONE, bi);
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testDivideByNegativeOneReturnsInverse() {
|
|
|
+// auto &NEGATIVE_ONE = math::bigdecimal::NEGATIVE_ONE;
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS((bi/NEGATIVE_ONE).to_string(), "-1000");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testDivisionWithMultipleMultSubSteps() {
|
|
|
+// math::bigdecimal bi{1112};
|
|
|
+// TS_ASSERT_EQUALS((bi/2).to_string(), "556");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testDivisionDroppingNumberOfCells() {
|
|
|
+// math::bigdecimal bi{1000000000ULL};
|
|
|
+// TS_ASSERT_EQUALS((bi/2).to_string(), "500000000");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testDivisionByBiggerNumberIsZero() {
|
|
|
+// math::bigdecimal bi{1000ULL};
|
|
|
+// TS_ASSERT_EQUALS((bi/1001).to_string(), "0");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testDivisionWithLargeNumbers() {
|
|
|
+// math::bigdecimal big{"999999998000000001"};
|
|
|
+// TS_ASSERT_EQUALS(big.to_string(), "999999998000000001");
|
|
|
+// TS_ASSERT_EQUALS((big/999999999ULL).to_string(),
|
|
|
+// "999999999");
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testModuloZeroThrows() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_THROWS(bi%0, std::domain_error);
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testModuloBiggerIsSameValue() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS(bi%2000, bi);
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testModuloSameNumberIsZero() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS(bi%1000, 0);
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testModuloDivisorIsZero() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// TS_ASSERT_EQUALS(bi%100, 0);
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testModuloDiffSignIsInverseElement() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// math::bigdecimal mod{13};
|
|
|
+// TS_ASSERT_EQUALS((bi%mod)+((-bi)%mod), mod);
|
|
|
+// }
|
|
|
+//
|
|
|
+// void testModuloNegativesIsNegative() {
|
|
|
+// math::bigdecimal bi{1000};
|
|
|
+// math::bigdecimal mod{13};
|
|
|
+// TS_ASSERT_EQUALS((bi%mod), -((-bi)%(-mod)));
|
|
|
+// }
|
|
|
+};
|