Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix:fit binary-exponent.cpp to guidelines #2463

Closed
wants to merge 16 commits into from
Closed
121 changes: 93 additions & 28 deletions math/binary_exponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* @file
* @brief C++ Program to find Binary Exponent Iteratively and Recursively.
*
* @details
* Calculate \f$a^b\f$ in \f$O(\log(b))\f$ by converting \f$b\f$ to a
* binary number. Binary exponentiation is also known as exponentiation by
* squaring.
Expand All @@ -19,53 +20,117 @@
* \f}
* Hence to calculate 2^10 we only need to multiply \f$2^8\f$ and \f$2^2\f$
* skipping \f$2^1\f$ and \f$2^4\f$.
*
* @author [Mann Mehta](https://github.com/mann2108)
ewd00010 marked this conversation as resolved.
Show resolved Hide resolved
* @author [ewd00010](https://github.com/ewd00010)
*/

#include <iostream>
#include <cassert> /// for assert
#include <iostream> /// for IO operations

ewd00010 marked this conversation as resolved.
Show resolved Hide resolved
/// Recursive function to calculate exponent in \f$O(\log(n))\f$ using binary
/// exponent.
int binExpo(int a, int b) {
if (b == 0) {
/**
* @brief Mathematical algorithms
* @namespace
*/
namespace math {
/**
* @brief Recursive function to calculate exponent in \f$O(\log(n))\f$ using
* binary exponent.
* @param a base number
* @param b exponent number
* @return 1 if the exponent number is 0 the return value will always be 1
* @return (res * res * a) if modulo 2 of exponential is 0
* @return (res * res) if modulo 2 of exponential is 1
*/
int64_t binExpo_recursive(int64_t a, uint64_t b) {
/*!
* Provided that b != 0, this function recursively calls itself, until an
* instance of it returns 1 (which eventually occurs due to b/2 for each
* call to binExpo). This triggers a chain reaction eventually leading
* back to the original call to binExpo returning. This works like a
* building a russian doll, first figure out however dolls you want to use (
* say, until a call to binExpo returns 1 ) and then assemble the dolls (
* with each return, res gets exponentially bigger )
*/
if (b == 0 || a == 1) {
return 1;
} else if(b == 1 || a == 0){
return a;
}
int res = binExpo(a, b / 2);

int64_t res = binExpo_recursive(a, b / 2);
if (b % 2) {
return res * res * a;
} else {
return res * res;
}
}

/// Iterative function to calculate exponent in \f$O(\log(n))\f$ using binary
/// exponent.
int binExpo_alt(int a, int b) {
int res = 1;
while (b > 0) {
/**
* @brief Iterative function to calculate exponent in \f$O(\log(n))\f$ using
* binary
+ exponent.
* @param a base number
* @param b exponential number
* @return res if the exponential number is >= 0
*/
int64_t binExpo_iterative(int64_t a, uint64_t b) {
/*!
* Provided b > 0, this function iteratively multiples the value res. Each
* iteration of the while loop, checks if the exponential number is binary,
* if so res is multiplied by the current value of a, for that iteration.
* Additionally, a is multiplied by itself and b is halved by itself.
*/
if (b == 0 || a == 1) {
return 1;
} else if(b == 1 || a == 0){
return a;
}

int64_t res = 1;
while (b > 0) { // if b is not a valid exponent
if (b % 2) {
res = res * a;
}
a = a * a;
b /= 2;
b >>= 1;
}
return res;
}
} // namespace math

/// Main function
int main() {
int a, b;
/// Give two numbers a, b
std::cin >> a >> b;
if (a == 0 && b == 0) {
std::cout << "Math error" << std::endl;
} else if (b < 0) {
std::cout << "Exponent must be positive !!" << std::endl;
} else {
int resRecurse = binExpo(a, b);
/// int resIterate = binExpo_alt(a, b);
/**
* @brief Self-test implementation
* @returns void
*/
static void tests() {
assert(math::binExpo_recursive(0, 1) == 0);
assert(math::binExpo_recursive(1, 0) == 1);
assert(math::binExpo_recursive(746584, 0) == 1);
assert(math::binExpo_recursive(1, 1) == 1);
assert(math::binExpo_recursive(2938374, 1) == 2938374);
assert(math::binExpo_recursive(3, 7) == 2187);
assert(math::binExpo_recursive(-31, 5) == -28629151);
assert(math::binExpo_recursive(0, 0) == 1);
assert(math::binExpo_recursive(1, 20) == 1);

/// Result of a^b (where '^' denotes exponentiation)
std::cout << resRecurse << std::endl;
/// std::cout << resIterate << std::endl;
}
assert(math::binExpo_iterative(0, 1) == 0);
assert(math::binExpo_iterative(1, 0) == 1);
assert(math::binExpo_iterative(746584, 0) == 1);
assert(math::binExpo_iterative(1, 1) == 1);
assert(math::binExpo_iterative(2938374, 1) == 2938374);
assert(math::binExpo_iterative(3, 7) == 2187);
assert(math::binExpo_iterative(-31, 5) == -28629151);
assert(math::binExpo_iterative(0, 0) == 1);
assert(math::binExpo_iterative(1, 20) == 1);
std::cout << "All tests have successfully passed!" << std::endl;
}

/**
* @brief Main function
* @returns 0 on exit
*/
int main() {
tests(); // run self-test implementations
return 0;
}