Number Number::operator[](const Range &range) const { int left = range.left(); int right = range.right(); if (left == 0 || right == 0) throw Exception("Number[0] operation is undefined (numbers are indexed 1..n)"); if (left < right) throw Exception("Number[x..y] operation where x < y is undefined"); int lefti; int righti; if (left > 0) { lefti = left + m_decimals - 1; } else { lefti = m_decimals + left; } if (right > 0) { righti = right + m_decimals - 1; } else { righti = m_decimals + right; } if ((lefti < 0 || righti < 0) || (m_digits.size() <= static_cast<size_t>(lefti) || m_digits.size() <= static_cast<size_t>(righti))) throw Exception("Number[x..y] out of bounds"); Number out; out.m_accuracy = m_accuracy; out.m_precision = m_precision; out.m_digits.clear(); out.m_digits.insert(out.m_digits.begin(), m_digits.cbegin() + righti, m_digits.cbegin() + lefti + 1); if (left > 0 && right < 0) { out.m_decimals = right * (-1); } out.m_trailingZeros = out.normalize(); return out; }
Number Number::inverse() const { // dzielenie przez 0 if (isNull()) throw Exception("Divison by 0 detected"); // wynikowa liczba Number result; result.m_digits.clear(); result.m_precision = m_precision; result.m_accuracy = m_accuracy; result.m_negative = m_negative; // dzieląca liczba Number integer = *this; int shiftBy = m_decimals; if (m_decimals > 0) { if (m_digits.size() >= static_cast<size_t>(m_precision)) { int cut = (m_digits.size() - m_precision); if (cut <= m_decimals) { integer.m_digits.erase(integer.m_digits.begin(), integer.m_digits.begin() + cut); integer.m_decimals -= cut; shiftBy -= cut; } } integer.shift(shiftBy); } // szukanie odwrotności 0.(dowolna ilość zer)1, lub jedynki if (integer.m_digits.size() == 1 && integer.m_digits.front() == 1) { result.m_digits.push_back(1); result.shift(m_decimals); return result; } // tymczasowa Number tmp(10); // jako że wrzucamy odwrotnie ... std::deque<char> numbers; int digit = 0; do { int cmp = tmp.compareWith(integer, true); if (cmp <= 0) { ++digit; tmp.subtract(integer, true); } else { numbers.push_front(digit); result.m_decimals++; digit = 0; tmp.shift(1); } } while(result.m_decimals <= m_precision && !tmp.isNull()); if (digit > 0) { numbers.push_front(digit); result.m_decimals++; } // teraz dodajemy do liczby result.m_digits.insert(result.m_digits.begin(), numbers.begin(), numbers.end()); result.m_digits.push_back(0); // 1 / 0,321 = 1000 * (1 / 321) result.shift(shiftBy); // dokładność if (m_accuracy > 0) { // todo: sprawdzić czy nie ma ładniejszego sposobu (jakiś range iterator?) int zeros = result.m_digits.size() - result.m_decimals - m_accuracy; for (auto li = result.m_digits.begin() + result.m_decimals; zeros > 0; li++, zeros--) { *li = 0; } } // sprzątanie result.normalize(); return result; }