Skip to content

Commit dae5fa6

Browse files
committed
Addressed decimal rounding issues in multiply
- [BREAKING] `radToDeg` and `degToRad` now require a `const int decimals` parameter, - `multiply` now takes a `const int decimals` parameter - `multiply` will now automatically round both numbers to desired precision before calculating the product, in order to reduce computation .
1 parent 881e26b commit dae5fa6

File tree

15 files changed

+89
-55
lines changed

15 files changed

+89
-55
lines changed

include/fn/calc.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "output.hpp"
4040

4141
#include <string>
42+
#include <util.hpp>
4243

4344
using namespace std::literals;
4445

@@ -154,7 +155,7 @@ namespace steppable::__internals::calc
154155
* @param[in] steps The number of steps to perform the multiplication.
155156
* @return The product of the two numbers as a string.
156157
*/
157-
std::string multiply(const std::string& a, const std::string& b, int steps = 2);
158+
std::string multiply(const std::string& a, const std::string& b, int steps = 2, int decimals = MAX_DECIMALS);
158159

159160
/**
160161
* @brief Raises a string representation of a number to a power.

include/types/data.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
/**************************************************************************************************
2+
* Copyright (c) 2023-2025 NWSOFT *
3+
* *
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy *
5+
* of this software and associated documentation files (the "Software"), to deal *
6+
* in the Software without restriction, including without limitation the rights *
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
8+
* copies of the Software, and to permit persons to whom the Software is *
9+
* furnished to do so, subject to the following conditions: *
10+
* *
11+
* The above copyright notice and this permission notice shall be included in all *
12+
* copies or substantial portions of the Software. *
13+
* *
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
20+
* SOFTWARE. *
21+
**************************************************************************************************/
22+
123
#pragma once
224

325
#include <string>

include/types/result.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ namespace steppable::types
104104
/// @brief Gets how the calculation is done.
105105
StatusType getStatus() const { return done; }
106106

107-
ResultT getResult() const { return result; }
107+
[[nodiscard("Result should be used")]] ResultT getResult() const { return result; }
108108

109109
/// @brief Gets the output of the calculation.
110110
[[nodiscard("Output should be used")]] std::string getOutput(size_t idx = 0) const

src/base/baseConvert/baseConvert.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ namespace steppable::__internals::calc
8686

8787
std::string baseConvert(const std::string& _number, const std::string& baseStr, const int steps)
8888
{
89-
const size_t base = std::stoll(static_cast<std::string>(baseStr));
89+
const size_t base = std::stoll(baseStr);
9090
auto numberOrig = static_cast<std::string>(_number);
9191
auto number = static_cast<std::string>(_number);
9292

src/calc/hyp/hyp.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ namespace steppable::__internals::calc
5353
{
5454
checkDecimalArg(&decimals);
5555

56-
const auto& twoX = multiply(x, "2", 0);
56+
const auto& twoX = multiply(x, "2", 0, decimals + 2);
5757
const auto& eTwoX = roundOff(power(static_cast<std::string>(constants::E), twoX, 0), decimals + 2);
5858
const auto& eX = roundOff(power(static_cast<std::string>(constants::E), x, 0), decimals + 2);
5959

6060
const auto& numerator = subtract(eTwoX, "1", 0);
61-
const auto& denominator = multiply("2", eX, 0);
61+
const auto& denominator = multiply("2", eX, 0, decimals + 2);
6262

6363
return divide(numerator, denominator, 0, decimals);
6464
}
@@ -67,12 +67,12 @@ namespace steppable::__internals::calc
6767
{
6868
checkDecimalArg(&decimals);
6969

70-
const auto& twoX = multiply(x, "2", 0);
70+
const auto& twoX = multiply(x, "2", 0, decimals + 2);
7171
const auto& eTwoX = roundOff(power(static_cast<std::string>(constants::E), twoX, 0), decimals + 2);
7272
const auto& eX = roundOff(power(static_cast<std::string>(constants::E), x, 0), decimals + 2);
7373

7474
const auto& numerator = add(eTwoX, "1", 0);
75-
const auto& denominator = multiply("2", eX, 0);
75+
const auto& denominator = multiply("2", eX, 0, decimals + 2);
7676

7777
return divide(numerator, denominator, 0, decimals);
7878
}
@@ -81,8 +81,8 @@ namespace steppable::__internals::calc
8181
{
8282
checkDecimalArg(&decimals);
8383

84-
const auto& numerator = sinh(x, decimals);
85-
const auto& denominator = cosh(x, decimals);
84+
const auto& numerator = sinh(x, decimals + 2);
85+
const auto& denominator = cosh(x, decimals + 2);
8686

8787
return divide(numerator, denominator, 0, decimals);
8888
}
@@ -91,7 +91,7 @@ namespace steppable::__internals::calc
9191
{
9292
checkDecimalArg(&decimals);
9393

94-
const auto& denominator = tanh(x, decimals);
94+
const auto& denominator = tanh(x, decimals + 1);
9595
if (isZeroString(denominator))
9696
{
9797
error("hyp::coth"s, $("hyp", "e1f6e8db-64cd-4882-b5b2-ddd1c79c1e57"));

src/calc/log/log.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ namespace steppable::__internals::calc
6767
// x + 4x + 1 x + 4x + 1
6868
const auto& x2 = power(x, "2", 0);
6969
const auto& x2Minus1 = subtract(x2, "1", 0);
70-
const auto& numerator = multiply("3", x2Minus1, 0);
71-
const auto& fourX = multiply(x, "4", 0);
70+
const auto& numerator = multiply("3", x2Minus1, 0, decimals);
71+
const auto& fourX = multiply(x, "4", 0, decimals);
7272

7373
auto denominator = add(x2, fourX, 0);
7474
denominator = add(denominator, "1", 0);
@@ -95,7 +95,7 @@ namespace steppable::__internals::calc
9595
auto xMinusExpYN = subtract(x, expYN, 0);
9696
auto xPlusExpYN = add(x, expYN, 0);
9797
auto fraction = divide(xMinusExpYN, xPlusExpYN, 0, static_cast<int>(decimals));
98-
auto twoXFraction = multiply(fraction, "2", 0);
98+
auto twoXFraction = multiply(fraction, "2", 0, decimals);
9999
yn1 = add(yn, twoXFraction, 0);
100100
error = abs(subtract(yn, yn1, 0), 0);
101101
} while (compare(error, epsilon, 0) == "1");

src/calc/multiply/multiply.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ using namespace steppable::__internals::calc;
4747

4848
namespace steppable::__internals::calc
4949
{
50-
std::string multiply(const std::string& _a, const std::string& _b, const int steps)
50+
std::string multiply(const std::string& _a, const std::string& _b, const int steps, const int decimals)
5151
{
5252
auto a = static_cast<std::string>(_a);
5353
auto b = static_cast<std::string>(_b);
@@ -62,7 +62,7 @@ namespace steppable::__internals::calc
6262
else
6363
resultIsNegative = false;
6464

65-
const auto& [aInteger, aDecimal, bInteger, bDecimal] = splitNumberArray;
65+
auto [aInteger, aDecimal, bInteger, bDecimal] = splitNumberArray;
6666
std::stringstream out;
6767
// Multiply by zero gives zero.
6868
if (isZeroString(a) or isZeroString(b))
@@ -72,7 +72,7 @@ namespace steppable::__internals::calc
7272
out << "0"; // Since a or b is zero, the result must be zero as well
7373
}
7474

75-
// Multiplying by 1 gives the another number.
75+
// Multiplying by 1 gives the other number.
7676
if (a == "1")
7777
{
7878
if (steps == 2)
@@ -112,6 +112,13 @@ namespace steppable::__internals::calc
112112
return out.str();
113113
}
114114

115+
// If the precision of a or b is higher than required, reduce it to simplify calculation
116+
if (aDecimal.length() + bDecimal.length() > decimals)
117+
{
118+
aDecimal = aDecimal.substr(0, decimals);
119+
bDecimal = bDecimal.substr(0, decimals);
120+
}
121+
115122
const std::string& aStr = aInteger + aDecimal;
116123
const std::string bStr = bInteger + bDecimal;
117124
std::vector<std::vector<int>> prodDigits;
@@ -200,10 +207,12 @@ int main(const int _argc, const char* _argv[])
200207
program.addPosArg('a', $("multiply", "1d54da58-ec3c-4888-80a8-c40565efb603"));
201208
program.addPosArg('b', $("multiply", "3db8b80f-9667-476a-b096-9323615dd461"));
202209
program.addKeywordArg("steps", 2, $("multiply", "5ed5291e-6269-4d76-a8f8-db5eec807955"));
210+
program.addKeywordArg("decimals", MAX_DECIMALS, $("multiply", "5ed5291e-6269-4d76-a8f8-db5eec807955"));
203211
program.addSwitch("profile", false, $("multiply", "eec47776-991b-40cc-9956-7227127d2c1f"));
204212
program.parseArgs();
205213

206214
int steps = program.getKeywordArgument("steps");
215+
int decimals = program.getKeywordArgument("decimals");
207216
bool profile = program.getSwitch("profile");
208217
const auto& aStr = program.getPosArg(0);
209218
const auto& bStr = program.getPosArg(1);
@@ -212,10 +221,10 @@ int main(const int _argc, const char* _argv[])
212221
{
213222
TIC(Column Method Multiplication)
214223
std::cout << $("multiply", "776a33fd-982a-4888-8b42-83b0f3797dc2") << "\n"
215-
<< multiply(aStr, bStr, steps) << '\n';
224+
<< multiply(aStr, bStr, steps, decimals) << '\n';
216225
TOC()
217226
}
218227
else
219-
std::cout << multiply(aStr, bStr, steps) << '\n';
228+
std::cout << multiply(aStr, bStr, steps, decimals) << '\n';
220229
}
221230
#endif

src/calc/power/power.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ namespace steppable::__internals::calc
129129
for (size_t i = 1; i < iter; i++)
130130
{
131131
std::string frac = divide(x, std::to_string(i), 0, static_cast<int>(decimals));
132-
term = multiply(term, frac, 0);
132+
term = multiply(term, frac, 0, decimals);
133133
sum = add(sum, term, 0);
134134
}
135135
return sum;

src/calc/power/powerReport.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ std::string reportPower(const std::string& _number,
128128
}
129129

130130
if (steps >= 1)
131-
ss << numberOrig << makeSuperscript(static_cast<std::string>(raiseTo)) << " = " << number;
131+
ss << numberOrig << makeSuperscript(raiseTo) << " = " << number;
132132
else if (steps == 0)
133133
ss << number;
134134

src/calc/root/root.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ namespace steppable::__internals::calc
146146
std::string number = static_cast<std::string>(_number);
147147
while (compare(number, "1", 0) == "0")
148148
{
149-
number = multiply(number, power("10", base, 0), 0);
149+
number = multiply(number, power("10", base, 0), 0, decimals);
150150
raisedTimes++;
151151
}
152152

@@ -196,7 +196,7 @@ namespace steppable::__internals::calc
196196
{
197197
auto result = rootSurd(_number, base);
198198
auto rootResult = _root(result.radicand, base, _decimals, 0);
199-
return multiply(rootResult, result.multiplier, 0);
199+
return multiply(rootResult, result.multiplier, 0, _decimals);
200200
}
201201

202202
return _root(_number, base, _decimals, steps);

0 commit comments

Comments
 (0)