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
117 changes: 90 additions & 27 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,29 +20,74 @@
* \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
*/

#include <iostream>

/// Recursive function to calculate exponent in \f$O(\log(n))\f$ using binary
/// exponent.
int binExpo(int a, int b) {
#include <cassert> /// for assert
#include <iostream> /// for cout
ewd00010 marked this conversation as resolved.
Show resolved Hide resolved
/**
* @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 0 if the exponential number is < 0 ( 0 representing NULL since
* < 0 is an invalid exponential to use )
* @return (res * res * a) if modulo 2 of exponential is 0
* @return (res * res) if modulo 2 of exponential is 1
*/
long long binExpo_recursive(long long a, long long b) {
ewd00010 marked this conversation as resolved.
Show resolved Hide resolved
/*!
* 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) {
return 1;
} else if (b < 0) { // if b is not a valid exponent
return 0;
}
int res = binExpo(a, b / 2);

long long 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
ewd00010 marked this conversation as resolved.
Show resolved Hide resolved
+ exponent.
* @param a base number
* @param b exponential number
* @return res if the exponential number is >= 0
* @return 0 if the exponential number is < 0 ( 0 representing NULL since
* < 0 is an invalid exponential to use )
*/
long long binExpo_iterative(long long a, long long 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) {
return 0;
}
long long res = 1;
while (b > 0) { // if b is not a valid exponent
if (b % 2) {
res = res * a;
}
Expand All @@ -50,22 +96,39 @@ int binExpo_alt(int a, int b) {
}
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);
using namespace math;
ewd00010 marked this conversation as resolved.
Show resolved Hide resolved
/**
* @brief self-test implementation
* @returns void
*/
static void tests() {
assert(binExpo_recursive(1, 0) == 1);
assert(binExpo_recursive(746584, 0) == 1);
assert(binExpo_recursive(1, 1) == 1);
assert(binExpo_recursive(2938374, 1) == 2938374);
assert(binExpo_recursive(3, 7) == 2187);
assert(binExpo_recursive(31, 5) == 28629151);
assert(binExpo_recursive(0, 0) == 1);
assert(binExpo_recursive(1, -20) == 0);

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

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