Skip to content

Commit

Permalink
Add a new function moveDecimalPlaces to rounding.hpp. (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
ZCG-coder committed May 8, 2024
2 parents fe78bdd + 85d084d commit 3e70044
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 53 deletions.
6 changes: 3 additions & 3 deletions Steppable.sublime-project
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[
{
"path": ".",
}
},
],
"debugger_configurations":
[
Expand Down Expand Up @@ -81,6 +81,6 @@
}
],
"settings": {
"SublimeLinter.linters.clangtidy.compile_commands": "${project_path}/build"
}
"SublimeLinter.linters.clangtidy.compile_commands": "${project_path}/build",
},
}
19 changes: 18 additions & 1 deletion include/rounding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,22 @@

namespace steppable::__internals::numUtils
{
/**
* @brief Round off a number to the nearest integer.
*
* @param[in] number The number to round.
* @return The rounded number.
*/
std::string roundOff(const std::string& number);
}

/**
* @brief Move the decimal places of a number.
*
* @param _number The number to process.
* @param places The desired decimal places to move. A negative amount indicates moving to the left, while a
* positive amount indicates moving to the right.
*
* @return The processed number.
*/
std::string moveDecimalPlaces(const std::string& _number, const long places);
} // namespace steppable::__internals::numUtils
16 changes: 8 additions & 8 deletions include/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,14 +209,6 @@ namespace steppable::__internals::numUtils
*/
std::string standardizeNumber(const std::string_view& _number);

/**
* @brief Round off a number to the nearest integer.
*
* @param[in] number The number to round.
* @return The rounded number.
*/
std::string roundOff(const std::string& number);

/**
* @fn constexpr bool isZeroString(const std::string_view& string)
* @brief Checks if a given string is a zero string.
Expand Down Expand Up @@ -321,6 +313,14 @@ namespace steppable::__internals::numUtils
* @return False if it is an integer, true otherwise.
*/
bool isDecimal(const std::string& number);

/**
* @brief Determines whether the number is a power of 10.
*
* @param number The number.
* @return True if it is a power of 10, false otherwise.
*/
bool isPowerOfTen(const std::string& number);
} // namespace steppable::__internals::numUtils

namespace steppable::__internals::stringUtils
Expand Down
65 changes: 41 additions & 24 deletions src/multiply/multiply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "rounding.hpp"
#include "util.hpp"

#include <sstream>
#include <string>
#include <string_view>
#include <vector>
Expand All @@ -45,30 +46,48 @@ using namespace steppable::__internals::arithmetic;

namespace steppable::__internals::arithmetic
{
/**
* @brief Determines the scale for a product of two numbers.
*
* @param[in] a Number 1,
* @param[in] b Number 2.
*
* @return The correct scale for their product.
*/
long long determineProductScale(const std::string& a, const std::string& b)
{
auto aScale = determineScale(roundOff(a));
auto bScale = determineScale(roundOff(b));

return aScale + bScale;
}

std::string multiply(const std::string_view& a, const std::string_view& b, const int steps)
std::string multiply(const std::string_view& _a, const std::string_view& _b, const int steps)
{
auto a = static_cast<std::string>(_a), b = static_cast<std::string>(_b);
std::stringstream out;
if (isZeroString(a) or isZeroString(b))
return "0"; // Since a or b is zero, the result must be zero as well
{
if (steps == 2)
out << "Since any of a or b is zero, the result must be zero as well.\n";
out << "0"; // Since a or b is zero, the result must be zero as well
}

// Multiplying by 1 gives the another number.
if (a == "1")
return static_cast<std::string>(b);
{
if (steps == 2)
out << "Since " << a << " is 1, the result is " << b << ".\n";
out << b;
return out.str();
}
if (b == "1")
return static_cast<std::string>(a);
{
if (steps == 2)
out << "Since " << b << " is 1, the result is " << a << ".\n";
out << a;
return out.str();
}

// Multiplying by a power of ten means moving the decimal places.
if (isPowerOfTen(a))
{
if (steps == 2)
out << "Since " << a << " is a power of 10, we can move the decimal places to obtain the result.\n";
out << moveDecimalPlaces(b, a.length() - 1);
return out.str();
}
if (isPowerOfTen(b))
{
if (steps == 2)
out << "Since " << b << " is a power of 10, we can move the decimal places to obtain the result.\n";
out << moveDecimalPlaces(a, b.length() - 1);
return out.str();
}

const auto& [splitNumberArray, aIsNegative, bIsNegative] = splitNumber(a, b, false, false);
bool resultIsNegative = false;
Expand Down Expand Up @@ -142,9 +161,8 @@ namespace steppable::__internals::arithmetic
finalProdDigits[indexDigit] = sum;
}

const auto scale = determineProductScale(static_cast<std::string>(a), static_cast<std::string>(b));
return reportMultiply(static_cast<std::string>(a),
static_cast<std::string>(b),
return reportMultiply(a,
b,
aStr,
bStr,
aDecimal,
Expand All @@ -154,7 +172,6 @@ namespace steppable::__internals::arithmetic
prodDigitsOut,
carries,
resultIsNegative,
scale,
steps);
}
} // namespace steppable::__internals::arithmetic
Expand Down
17 changes: 5 additions & 12 deletions src/multiply/multiplyReport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

#include "multiplyReport.hpp"

#include "fn/basicArithm.hpp"
#include "rounding.hpp"
#include "symbols.hpp"
#include "util.hpp"

Expand All @@ -43,7 +43,6 @@
using namespace steppable::__internals::symbols;
using namespace steppable::__internals::numUtils;
using namespace steppable::__internals::stringUtils;
using namespace steppable::__internals::arithmetic;

std::string reportMultiply(const std::string& a,
const std::string& b,
Expand All @@ -56,7 +55,6 @@ std::string reportMultiply(const std::string& a,
const std::vector<std::vector<int>>& prodDigitsOut,
const std::vector<std::vector<int>>& carries,
const bool resultIsNegative,
const long long scale,
const int steps)
{
std::stringstream ss;
Expand Down Expand Up @@ -110,20 +108,15 @@ std::string reportMultiply(const std::string& a,
ss << a << " " MULTIPLY " " << b << " = ";
if (resultIsNegative)
ss << '-';
const auto vector = replaceLeadingZeros(finalProdDigits);
const auto vector = removeLeadingZeros(finalProdDigits);

std::string out;
for (const int i : vector)
if (i >= 0)
out += std::to_string(i);
out += std::to_string(i);

// Add the decimal point.
auto aDecimals = aDecimal.length(), bDecimals = bDecimal.length();
if (aDecimals + bDecimals > 0)
{
out.insert(out.end() - aDecimals - bDecimals, '.');
out = removeTrailingZeros(out);
}
auto places = aDecimal.length() + bDecimal.length();
out = moveDecimalPlaces(out, -places);

ss << standardizeNumber(out);
return ss.str();
Expand Down
1 change: 0 additions & 1 deletion src/multiply/multiplyReport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,4 @@ std::string reportMultiply(const std::string& a,
const std::vector<std::vector<int>>& prodDigitsOut,
const std::vector<std::vector<int>>& carries,
bool resultIsNegative = false,
long long scale = 0,
int steps = 2);
6 changes: 3 additions & 3 deletions src/root/root.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ namespace steppable::__internals::arithmetic
std::string root(const std::string& _number, const std::string& base, const size_t _decimals)
{
auto decimals = _decimals + 1;
size_t raised_times = 0;
size_t raisedTimes = 0;
std::string number = static_cast<std::string>(_number);
while (compare(number, "1", 0) == "0")
{
number = multiply(number, power("10", base, 0), 0);
raised_times++;
raisedTimes++;
}

auto x = number, y = "0"s, allowedError = "0." + std::string(decimals - 1, '0') + "1";
size_t idx = 0;
auto denominator = "1" + std::string(raised_times, '0');
auto denominator = "1" + std::string(raisedTimes, '0');

while (true)
{
Expand Down
43 changes: 43 additions & 0 deletions src/rounding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,47 @@ namespace steppable::__internals::numUtils
return integer + "." + decimal;
return arithmetic::add(integer, "1", 0) + "." + decimal;
}

std::string moveDecimalPlaces(const std::string& _number, const long places)
{
auto number = _number;
// No change
if (not places)
return number;

// Is the number an integer?
if (isInteger(number))
number += ".0";
auto splitNumberResult = splitNumber(number, "0", false, false, true, false).splitNumberArray;
auto integer = splitNumberResult[0], decimal = splitNumberResult[1];
auto repetitions = std::abs(places);

// Move decimal places to the right
if (places > 0)
{
for (size_t _ = 0; _ < repetitions; _++)
if (decimal.length() > 0)
{
integer += decimal[0];
decimal.erase(decimal.cbegin());
}
else
integer += '0';
}
// Move decimal places to the left
else if (places < 0)
{
for (size_t _ = 0; _ < repetitions; _++)
if (integer.length() > 0)
{
decimal = integer.back() + decimal;
integer.pop_back();
}
else
decimal = '0' + decimal;
}

auto result = integer + "." + decimal;
return standardizeNumber(result);
}
} // namespace steppable::__internals::numUtils
14 changes: 13 additions & 1 deletion src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ namespace steppable::__internals::numUtils
}

auto removeLeadingZeros(const std::vector<int>& vector) -> std::decay_t<decltype(vector)>
{
{
const auto firstNonZero = std::ranges::find_if(vector, [](const int num) { return num != 0; });

// Create a new vector with the non-zero elements
Expand Down Expand Up @@ -245,6 +245,18 @@ namespace steppable::__internals::numUtils
}

bool isDecimal(const std::string& number) { return not isInteger(number); }

bool isPowerOfTen(const std::string& number)
{
if (number == "1")
return true; // 1 is a power of 10.
if (number.front() != '1')
return false; // The number must start with 1.
for (const char c : number.substr(1, number.length()))
if (c != '0' and c != '.')
return false; // The rest of the number must be zeros or decimal points.
return true;
}
} // namespace steppable::__internals::numUtils

namespace steppable::__internals::stringUtils
Expand Down

0 comments on commit 3e70044

Please sign in to comment.