Sfoglia il codice sorgente

Adding A-B operation, and tests

Samuel Jaffe 8 anni fa
parent
commit
27ae458c19
3 ha cambiato i file con 54 aggiunte e 11 eliminazioni
  1. 1 0
      include/biginteger.h
  2. 33 11
      src/biginteger.cpp
  3. 20 0
      test/biginteger.t.h

+ 1 - 0
include/biginteger.h

@@ -14,6 +14,7 @@ namespace math {
   class biginteger {
   public:
     using data_type = std::vector<int32_t>;
+    static biginteger const ZERO, ONE, NEGATIVE_ONE;
     static constexpr int32_t const MAX_SEG   { 999999999};
     static constexpr int32_t const OVER_SEG  {1000000000};
     static constexpr int32_t const SEG_DIGITS{         9};

+ 33 - 11
src/biginteger.cpp

@@ -53,11 +53,11 @@ biginteger & operator+=(biginteger & rhs, biginteger const & lhs) {
   return rhs;
 }
 
-//biginteger & operator-=(biginteger & rhs, biginteger const & lhs) {
-//  swap(rhs, rhs - lhs);
-//  return rhs;
-//}
-//
+biginteger & operator-=(biginteger & rhs, biginteger const & lhs) {
+  swap(rhs, rhs - lhs);
+  return rhs;
+}
+
 //biginteger & operator*=(biginteger & rhs, biginteger const & lhs) {
 //  swap(rhs, rhs * lhs);
 //  return rhs;
@@ -75,6 +75,8 @@ biginteger biginteger::operator-() const {
 }
 
 biginteger math::operator+(biginteger const & rhs, biginteger const & lhs) {
+  if (lhs == biginteger::ZERO) { return rhs; }
+  else if (rhs == biginteger::ZERO) { return lhs; }
   if (rhs.is_negative == lhs.is_negative) {
     return {rhs.is_negative, detail::add(rhs.data, lhs.data)};
   } else {
@@ -89,6 +91,23 @@ biginteger math::operator+(biginteger const & rhs, biginteger const & lhs) {
   }
 }
 
+biginteger math::operator-(biginteger const & rhs, biginteger const & lhs) {
+  if (lhs == biginteger::ZERO) { return rhs; }
+  else if (rhs == biginteger::ZERO) { return -lhs; }
+  if (rhs.is_negative != lhs.is_negative) {
+    return {rhs.is_negative, detail::add(rhs.data, lhs.data)};
+  } else {
+    auto cmp = detail::compare(rhs.data, lhs.data);
+    if (cmp == 0) {
+      return 0;
+    } else if (cmp > 0) {
+      return {rhs.is_negative, detail::subtract_nounderflow(rhs.data, lhs.data)};
+    } else {
+      return {!lhs.is_negative, detail::subtract_nounderflow(lhs.data, rhs.data)};
+    }
+  }
+}
+
 namespace detail {
 #define IMPL_COMPARE(expr) \
   if (rhs expr < lhs expr) return -1; \
@@ -106,7 +125,7 @@ namespace detail {
   data_type add(data_type const & rhs, data_type const & lhs) {
     data_type::size_type const rbnd = rhs.size(), lbnd = lhs.size();
     data_type::size_type const ubnd = std::max(rbnd, lbnd);
-    data_type rval(ubnd);
+    data_type rval(ubnd+1);
     // Add
     for (data_type::size_type i = 0; i < rbnd; ++i) {
       rval[i] += rhs[i];
@@ -115,16 +134,13 @@ namespace detail {
       rval[i] += lhs[i];
     }
     // Carry
-    for (data_type::size_type i = 0; i < ubnd-1; ++i) {
+    for (data_type::size_type i = 0; i < ubnd; ++i) {
       if (rval[i] > biginteger::MAX_SEG) {
         rval[i] -= biginteger::OVER_SEG;
         rval[i+1] += 1;
       }
     }
-    if (rval[ubnd-1] > biginteger::MAX_SEG) {
-      rval[ubnd-1] -= biginteger::OVER_SEG;
-      rval.push_back(1);
-    }
+    if (rval[ubnd] == 0) { rval.pop_back(); }
     return rval;
   }
   
@@ -147,6 +163,12 @@ namespace detail {
   }
 }
 
+bool math::operator==(biginteger const & rhs, biginteger const & lhs) {
+  return rhs.is_negative == lhs.is_negative && detail::compare(rhs.data, lhs.data) == 0;
+}
+
+biginteger const biginteger::ZERO{0}, biginteger::ONE{1}, biginteger::NEGATIVE_ONE{-1};
+
 #include <iomanip>
 #include <sstream>
 

+ 20 - 0
test/biginteger.t.h

@@ -32,4 +32,24 @@ public:
     math::biginteger bi{1000};
     TS_ASSERT_EQUALS((bi+(-999)).to_string(), "1");
   }
+  
+  void testSubSelfIsZero() {
+    math::biginteger bi{1000};
+    TS_ASSERT_EQUALS((bi-bi).to_string(), "0");
+  }
+  
+  void testNegativeMinusNegativeIncreateAbs() {
+    math::biginteger bi{-1000};
+    TS_ASSERT_EQUALS((bi-100).to_string(), "-1100");
+  }
+  
+  void testSubLargerGivesNegative() {
+    math::biginteger bi{1000};
+    TS_ASSERT_EQUALS((bi-1001).to_string(), "-1");
+  }
+  
+  void testSubSmallerGivesPositive() {
+    math::biginteger bi{1000};
+    TS_ASSERT_EQUALS((bi-999).to_string(), "1");
+  }
 };