So, I'm trying to make Luhn's algorithm in C, but it doesn't return the correct values when running it.
//Luhn's Algorithm
int tsum = 0;
if (count % 2 != 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 != 0)
{
tsum += (cardNum % 10);
}
else
{
tsum += (cardNum % 10)*2;
}
cardNum /= 10;
}
}
else
if (count % 2 == 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 == 0)
{
tsum += (cardNum % 10);
}
else
{
tsum += (cardNum % 10)*2;
}
cardNum /= 10;
}
}
tsum %= 10;
I have spent hours trying to troubleshoot and find the issue, count represents the number of digits in the card number, the rest define themselves.
I would appreciate somebody to tell me what I'm doing wrong, thank you.
EDIT: Apologies, cardNum is a long long. And I am expecitng a value of 0 for tsum when inputting any card number from Paypal's Standard Test Cards. I would also like to add, in my mind what this code should do is: using the checks for even and odd it will start from the rightmost digit and add it to tsum, every other digit will do the same. Then starting from the 2nd rightmost digit, the digit is multiplied by 2 then added to tsum, with every other digit doing the same. Then, the last line will check the rightmost digit of the current tsum and will tell me if the card is valid according to Luhn's Algorithm.
Here is what I usually do if I "try to implement" something I am not sure about: I use an interactive language, such as Common Lisp, tinker and test interactively until it works. Then, I usually have some good template I can use to write it in a less powerful language such as C.
(defun luhn-method (n)
(mod
(loop
for x = n then (floor x 10)
while (> x 0)
for double = nil then (not double)
for digit = (mod x 10)
for factor = (if double 2 1)
for y = (let ((a (* digit factor)))
(if (> a 9) (- a 9) a))
do (format t "~%~a" (list :x x :double double :digit digit :factor factor :y y))
summing y)
10))
I did this just from reading the wikipedia page about Luhn method (the german wiki page is easier to understand because it shows a simple exampple, while being less verbose than the english version).
From your Paypal site, the first number produces
(luhn-method 378282246310005)
(X 378282246310005 DOUBLE NIL DIGIT 5 FACTOR 1 Y 5)
(X 37828224631000 DOUBLE T DIGIT 0 FACTOR 2 Y 0)
(X 3782822463100 DOUBLE NIL DIGIT 0 FACTOR 1 Y 0)
(X 378282246310 DOUBLE T DIGIT 0 FACTOR 2 Y 0)
(X 37828224631 DOUBLE NIL DIGIT 1 FACTOR 1 Y 1)
(X 3782822463 DOUBLE T DIGIT 3 FACTOR 2 Y 6)
(X 378282246 DOUBLE NIL DIGIT 6 FACTOR 1 Y 6)
(X 37828224 DOUBLE T DIGIT 4 FACTOR 2 Y 8)
(X 3782822 DOUBLE NIL DIGIT 2 FACTOR 1 Y 2)
(X 378282 DOUBLE T DIGIT 2 FACTOR 2 Y 4)
(X 37828 DOUBLE NIL DIGIT 8 FACTOR 1 Y 8)
(X 3782 DOUBLE T DIGIT 2 FACTOR 2 Y 4)
(X 378 DOUBLE NIL DIGIT 8 FACTOR 1 Y 8)
(X 37 DOUBLE T DIGIT 7 FACTOR 2 Y 5)
(X 3 DOUBLE NIL DIGIT 3 FACTOR 1 Y 3)
0
making it easy to see every single step of the algorithm and convincing yourself it is correct.
To port this to C, first we need to explore, if C has an integer type wide enough for those credit card numbers (lisp has large integers by default - one thing less to worry about in our prototype). Lisp again:
(log 378282246310005 2)
48.426456
So, we need a 64 bit variable and should be good.
Since integers in C are implementation/platform/system specific, we should use some header file, giving us the correct type:
#include <stdint.h>
In there, the 64 bit unsigned integer is defined as uint64_t and if your compiler and your header files are correct for your system, using that makes sure, you do not get it wrong. The native "unsigned long long" etc. are just guesswork and not portable.
With that in place, we can simply port the code above to C:
uint64_t luhn(uint64_t n) {
uint64_t x = n;
uint64_t sum = 0;
uint64_t factor = 1;
while (x > 0) {
uint64_t y = (x % 10) * factor;
if (y > 9)
y = y - 9;
sum += y;
x = x / 10;
if (1 == factor) {
factor = 2;
} else {
factor = 1;
}
}
return sum % 10;
}
Summary:
A proper tool set helps getting stuff done. If you don't know yet, how to use a C debugger and step through code line by line while watching the content of variables, an interactive programming language is probably easier for you for prototyping.
Thank you for your help, I was able to solve this issue as it seems I had missed a step in Luhn's Algorithm.
//Luhn's Algorithm
int tsum = 0;
int luhn;
if (count % 2 != 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 != 0)
{
luhn = (cardNum % 10);
tsum += luhn;
}
else
{
luhn = (cardNum % 10) * 2;
if (luhn > 9)
{
tsum += (luhn - 9);
}
else
{
tsum += luhn;
}
}
cardNum /= 10;
}
}
else if (count % 2 == 0)
{
for (int tempcount = count; tempcount > 0; tempcount--)
{
if (tempcount % 2 == 0)
{
luhn = (cardNum % 10);
tsum += luhn;
}
else
{
luhn = (cardNum % 10) * 2;
if (luhn > 9)
{
tsum += (luhn - 9);
}
else
{
tsum += luhn;
}
}
cardNum /= 10;
}
}
tsum %= 10;
Here, I defined luhn as the next integer to be added to the tsum, in doing this I was able to fill in the missing step by subtracting 9 before adding to tsum if luhn exceeded 9.
This feels like a basic question but I couldn't find a definitive answer so far.
I would like to implement an efficient function round_to_nearest(int x, int multiple), that rounds a signed integer x to the nearest multiple of multiple, avoiding using floating point arithmetic if possible.
Example output:
round_to_nearest(14, 5);
15
round_to_nearest(16, 5);
15
round_to_nearest(23, 5);
25
round_to_nearest(22, 5);
20
round_to_nearest(-23, 5);
-25
round_to_nearest(-22, 5);
-20
In integer arithmetic, if n is positive, add m/2, else subtract m/2, then divide by m (truncating integer divide), then multiply by m:
int round_to_nearest( int n, int m )
{
return (( n + ((n < 0) ? -m : m) / 2) / m ) * m ;
}
int main()
{
int test[] = {16, 23, 22, -23, -22} ;
int m = 5 ;
for( int i = 0; i < sizeof(test) / sizeof(*test); i++ )
{
printf(" round_to_nearest( %d, %d ) = %d\n", test[i], m,
round_to_nearest( test[i], m ) ) ;
}
return 0;
}
Output of test:
round_to_nearest( 16, 5 ) = 15
round_to_nearest( 23, 5 ) = 25
round_to_nearest( 22, 5 ) = 20
round_to_nearest( -23, 5 ) = -25
round_to_nearest( -22, 5 ) = -20
One caveat is that m must be > 0 - which in this context makes sense, I would accept that as a precondition for correct operation; checking for it as a runtime error is probably unnecessary, but you might include an assert to protect against programmer semantic error:
assert( m > 0 ) ;
Standard library asserts are removed when NDEBUG is defined - normally when debug support is disabled.
For positive numbers:
add half of the multiple to x
then perform integer division, which drops the fractional part
then multiply by the multiple to get the final answer
For negative numbers, the first step is a subtraction, instead of addition.
int round_to_nearest(int x, int multiple)
{
if (x >= 0)
return ((x + multiple / 2) / multiple) * multiple;
else
return ((x - multiple / 2) / multiple) * multiple;
}
In order to round to the next multiple in the direction of zero (i.e. down for positive numbers and up for negative numbers), all you have to do is to divide by that multiple and then multiply the result with the multiple. The rounding towards zero will be accomplished by the truncation in the division.
int round_toward_zero( int num, int multiple )
{
int quotient;
quotient = num / multiple;
return quotient * multiple;
}
However, since you stated that you wanted to round to the nearest multiple instead of the next multiple in the direction of zero, we must do the same thing, but we must add a small correction in cases in which we want to round in the other direction:
For positive numbers, if the remainder of the division is at least half of the multiple, then we must add 1 to the quotient before multiplying with the multiple, so that it is rounded away from zero.
For negative numbers, if the remainder of the devision is not more than half of the multiple we must add -1 to the quotient before multiplying with the multiple, so that it is rounded away from zero.
Therefore, in the following code, the variable correction can have the value -1, 0 or +1. For positive numbers, it will be either 0 or +1, and for negative numbers, it will be either -1 or 0.
#include <stdio.h>
int round_to_nearest( int num, int multiple )
{
int quotient, remainder, correction;
quotient = num / multiple;
remainder = num % multiple;
correction = remainder / ( (multiple + 1 ) / 2 );
return (quotient + correction) * multiple;
}
int main( void )
{
printf( "%d\n", round_to_nearest(14, 5) );
printf( "%d\n", round_to_nearest(16, 5) );
printf( "%d\n", round_to_nearest(23, 5) );
printf( "%d\n", round_to_nearest(22, 5) );
printf( "%d\n", round_to_nearest(-23, 5) );
printf( "%d\n", round_to_nearest(-22, 5) );
}
Output:
15
15
25
20
-25
-20
Integer division truncates towards zero; which is 0.5 smaller (in magnitude, on average) than a rounded to nearest result.
If you add the magnitude of 0.5 * divisor to the magnitude of the numerator, then the result will be 0.5 larger.
In other words, for unsigned integers:
result = (numerator + divisor/2) / divisor;
..or alternatively (with less rounding error when the divisor is odd, and higher risk of overflow - e.g. if numerator is INT_MAX):
result = (numerator*2 + divisor) / (divisor * 2);
For signed integers "magnitude" isn't "value"; and it becomes a mess when the numerator and divisor have a different sign. To fix that:
if( (numerator < 0) && (divisor < 0) ||
(numerator >= 0) && (divisor |= 0) ) {
/* Numerator and divisor have same sign */
result = (numerator*2 + divisor) / (divisor * 2);
} else {
/* Numerator and divisor have different sign */
result = (numerator*2 - divisor) / (divisor * 2);
}
To round to the nearest multiple, you just multiply by the divisor after the "round to nearest". The code becomes:
if( (numerator < 0) && (multiple < 0) ||
(numerator >= 0) && (multiple |= 0) ) {
/* Numerator and multiple have same sign */
result = (numerator*2 + multiple) / (multiple * 2);
} else {
/* Numerator and multiple have different sign */
result = (numerator*2 - multiple) / (multiple * 2);
}
result *= multiple;
While learning Bit operations in c,I was searching for code to multiply two numbers using only bit operations , I found the following code!. I am unable to understand how ternary operator is working in the following scenario and producing the correct o/p.
#include<stdio.h>
static int multiply (int x, int y)
{
return y==0?0:((y&1) ==1?x:0)+multiply(x<<1,y>>1);
}
int main()
{
printf("%d",multiply(2,3));
return 0;
}
Can someone please explain how is the above code working?.
That is not using "only bit operations", since it's using + to add numbers.
Maybe indenting can help break up the complicated expression:
return (y == 0 ? 0
: (y & 1) == 1 ? x
: 0)
+ multiply(x << 1, y >> 1);
Basically it's a recursive addition, that stops when y reaches 0. If the least significant bit of y is set, x is added to the result, else it is not. On each recursion, one bit of y is dropped so that it eventually will reach 0. The value of x is shifted to the left, very much like when doing multiplication by hand.
For instance if x = 3 (binary 11) and y = 6 (binary 110), it will compute
0 * 3 + 1 * 6 + 1 * 12 = 18
And of course 18 is 3 * 6.
Each recursion step is written as a * b where a is the least significant bit of y at that step (reading from the left, you get 0, 1, 1 which is the bits of y starting with the least significant bit) and b is the value of x at that step.
If y is odd, x * y = x + (x * 2) * (y / 2)
If y is even, x * y = (x * 2) * (y / 2)
With the logic above, and use recursion until y = 0.
If you are struggling understanding a complex nested use of the conditional operator, then simply expand it to an if statement:
static int multiply (int x, int y)
{
if (y==0)
return 0;
else
return ((y&1) ==1?x:0)+multiply(x<<1,y>>1);
}
And then expand the inner conditional operator:
static int multiply (int x, int y)
{
if (y == 0)
return 0;
else if ((y&1) == 1)
return x + multiply(x<<1, y>>1);
else return
return multiply(x<<1, y>>1);
}
Once you've expanded it like this, it should be clear what the expression is doing.
What is the most efficient way given to raise an integer to the power of another integer in C?
// 2^3
pow(2,3) == 8
// 5^5
pow(5,5) == 3125
Exponentiation by squaring.
int ipow(int base, int exp)
{
int result = 1;
for (;;)
{
if (exp & 1)
result *= base;
exp >>= 1;
if (!exp)
break;
base *= base;
}
return result;
}
This is the standard method for doing modular exponentiation for huge numbers in asymmetric cryptography.
Note that exponentiation by squaring is not the most optimal method. It is probably the best you can do as a general method that works for all exponent values, but for a specific exponent value there might be a better sequence that needs fewer multiplications.
For instance, if you want to compute x^15, the method of exponentiation by squaring will give you:
x^15 = (x^7)*(x^7)*x
x^7 = (x^3)*(x^3)*x
x^3 = x*x*x
This is a total of 6 multiplications.
It turns out this can be done using "just" 5 multiplications via addition-chain exponentiation.
n*n = n^2
n^2*n = n^3
n^3*n^3 = n^6
n^6*n^6 = n^12
n^12*n^3 = n^15
There are no efficient algorithms to find this optimal sequence of multiplications. From Wikipedia:
The problem of finding the shortest addition chain cannot be solved by dynamic programming, because it does not satisfy the assumption of optimal substructure. That is, it is not sufficient to decompose the power into smaller powers, each of which is computed minimally, since the addition chains for the smaller powers may be related (to share computations). For example, in the shortest addition chain for a¹⁵ above, the subproblem for a⁶ must be computed as (a³)² since a³ is re-used (as opposed to, say, a⁶ = a²(a²)², which also requires three multiplies).
If you need to raise 2 to a power. The fastest way to do so is to bit shift by the power.
2 ** 3 == 1 << 3 == 8
2 ** 30 == 1 << 30 == 1073741824 (A Gigabyte)
Here is the method in Java
private int ipow(int base, int exp)
{
int result = 1;
while (exp != 0)
{
if ((exp & 1) == 1)
result *= base;
exp >>= 1;
base *= base;
}
return result;
}
An extremely specialized case is, when you need say 2^(-x to the y), where x, is of course is negative and y is too large to do shifting on an int. You can still do 2^x in constant time by screwing with a float.
struct IeeeFloat
{
unsigned int base : 23;
unsigned int exponent : 8;
unsigned int signBit : 1;
};
union IeeeFloatUnion
{
IeeeFloat brokenOut;
float f;
};
inline float twoToThe(char exponent)
{
// notice how the range checking is already done on the exponent var
static IeeeFloatUnion u;
u.f = 2.0;
// Change the exponent part of the float
u.brokenOut.exponent += (exponent - 1);
return (u.f);
}
You can get more powers of 2 by using a double as the base type.
(Thanks a lot to commenters for helping to square this post away).
There's also the possibility that learning more about IEEE floats, other special cases of exponentiation might present themselves.
power() function to work for Integers Only
int power(int base, unsigned int exp){
if (exp == 0)
return 1;
int temp = power(base, exp/2);
if (exp%2 == 0)
return temp*temp;
else
return base*temp*temp;
}
Complexity = O(log(exp))
power() function to work for negative exp and float base.
float power(float base, int exp) {
if( exp == 0)
return 1;
float temp = power(base, exp/2);
if (exp%2 == 0)
return temp*temp;
else {
if(exp > 0)
return base*temp*temp;
else
return (temp*temp)/base; //negative exponent computation
}
}
Complexity = O(log(exp))
If you want to get the value of an integer for 2 raised to the power of something it is always better to use the shift option:
pow(2,5) can be replaced by 1<<5
This is much more efficient.
int pow( int base, int exponent)
{ // Does not work for negative exponents. (But that would be leaving the range of int)
if (exponent == 0) return 1; // base case;
int temp = pow(base, exponent/2);
if (exponent % 2 == 0)
return temp * temp;
else
return (base * temp * temp);
}
Just as a follow up to comments on the efficiency of exponentiation by squaring.
The advantage of that approach is that it runs in log(n) time. For example, if you were going to calculate something huge, such as x^1048575 (2^20 - 1), you only have to go thru the loop 20 times, not 1 million+ using the naive approach.
Also, in terms of code complexity, it is simpler than trying to find the most optimal sequence of multiplications, a la Pramod's suggestion.
Edit:
I guess I should clarify before someone tags me for the potential for overflow. This approach assumes that you have some sort of hugeint library.
Late to the party:
Below is a solution that also deals with y < 0 as best as it can.
It uses a result of intmax_t for maximum range. There is no provision for answers that do not fit in intmax_t.
powjii(0, 0) --> 1 which is a common result for this case.
pow(0,negative), another undefined result, returns INTMAX_MAX
intmax_t powjii(int x, int y) {
if (y < 0) {
switch (x) {
case 0:
return INTMAX_MAX;
case 1:
return 1;
case -1:
return y % 2 ? -1 : 1;
}
return 0;
}
intmax_t z = 1;
intmax_t base = x;
for (;;) {
if (y % 2) {
z *= base;
}
y /= 2;
if (y == 0) {
break;
}
base *= base;
}
return z;
}
This code uses a forever loop for(;;) to avoid the final base *= base common in other looped solutions. That multiplication is 1) not needed and 2) could be int*int overflow which is UB.
more generic solution considering negative exponenet
private static int pow(int base, int exponent) {
int result = 1;
if (exponent == 0)
return result; // base case;
if (exponent < 0)
return 1 / pow(base, -exponent);
int temp = pow(base, exponent / 2);
if (exponent % 2 == 0)
return temp * temp;
else
return (base * temp * temp);
}
The O(log N) solution in Swift...
// Time complexity is O(log N)
func power(_ base: Int, _ exp: Int) -> Int {
// 1. If the exponent is 1 then return the number (e.g a^1 == a)
//Time complexity O(1)
if exp == 1 {
return base
}
// 2. Calculate the value of the number raised to half of the exponent. This will be used to calculate the final answer by squaring the result (e.g a^2n == (a^n)^2 == a^n * a^n). The idea is that we can do half the amount of work by obtaining a^n and multiplying the result by itself to get a^2n
//Time complexity O(log N)
let tempVal = power(base, exp/2)
// 3. If the exponent was odd then decompose the result in such a way that it allows you to divide the exponent in two (e.g. a^(2n+1) == a^1 * a^2n == a^1 * a^n * a^n). If the eponent is even then the result must be the base raised to half the exponent squared (e.g. a^2n == a^n * a^n = (a^n)^2).
//Time complexity O(1)
return (exp % 2 == 1 ? base : 1) * tempVal * tempVal
}
int pow(int const x, unsigned const e) noexcept
{
return !e ? 1 : 1 == e ? x : (e % 2 ? x : 1) * pow(x * x, e / 2);
//return !e ? 1 : 1 == e ? x : (((x ^ 1) & -(e % 2)) ^ 1) * pow(x * x, e / 2);
}
Yes, it's recursive, but a good optimizing compiler will optimize recursion away.
One more implementation (in Java). May not be most efficient solution but # of iterations is same as that of Exponential solution.
public static long pow(long base, long exp){
if(exp ==0){
return 1;
}
if(exp ==1){
return base;
}
if(exp % 2 == 0){
long half = pow(base, exp/2);
return half * half;
}else{
long half = pow(base, (exp -1)/2);
return base * half * half;
}
}
I use recursive, if the exp is even,5^10 =25^5.
int pow(float base,float exp){
if (exp==0)return 1;
else if(exp>0&&exp%2==0){
return pow(base*base,exp/2);
}else if (exp>0&&exp%2!=0){
return base*pow(base,exp-1);
}
}
In addition to the answer by Elias, which causes Undefined Behaviour when implemented with signed integers, and incorrect values for high input when implemented with unsigned integers,
here is a modified version of the Exponentiation by Squaring that also works with signed integer types, and doesn't give incorrect values:
#include <stdint.h>
#define SQRT_INT64_MAX (INT64_C(0xB504F333))
int64_t alx_pow_s64 (int64_t base, uint8_t exp)
{
int_fast64_t base_;
int_fast64_t result;
base_ = base;
if (base_ == 1)
return 1;
if (!exp)
return 1;
if (!base_)
return 0;
result = 1;
if (exp & 1)
result *= base_;
exp >>= 1;
while (exp) {
if (base_ > SQRT_INT64_MAX)
return 0;
base_ *= base_;
if (exp & 1)
result *= base_;
exp >>= 1;
}
return result;
}
Considerations for this function:
(1 ** N) == 1
(N ** 0) == 1
(0 ** 0) == 1
(0 ** N) == 0
If any overflow or wrapping is going to take place, return 0;
I used int64_t, but any width (signed or unsigned) can be used with little modification. However, if you need to use a non-fixed-width integer type, you will need to change SQRT_INT64_MAX by (int)sqrt(INT_MAX) (in the case of using int) or something similar, which should be optimized, but it is uglier, and not a C constant expression. Also casting the result of sqrt() to an int is not very good because of floating point precission in case of a perfect square, but as I don't know of any implementation where INT_MAX -or the maximum of any type- is a perfect square, you can live with that.
I have implemented algorithm that memorizes all computed powers and then uses them when need. So for example x^13 is equal to (x^2)^2^2 * x^2^2 * x where x^2^2 it taken from the table instead of computing it once again. This is basically implementation of #Pramod answer (but in C#).
The number of multiplication needed is Ceil(Log n)
public static int Power(int base, int exp)
{
int tab[] = new int[exp + 1];
tab[0] = 1;
tab[1] = base;
return Power(base, exp, tab);
}
public static int Power(int base, int exp, int tab[])
{
if(exp == 0) return 1;
if(exp == 1) return base;
int i = 1;
while(i < exp/2)
{
if(tab[2 * i] <= 0)
tab[2 * i] = tab[i] * tab[i];
i = i << 1;
}
if(exp <= i)
return tab[i];
else return tab[i] * Power(base, exp - i, tab);
}
Here is a O(1) algorithm for calculating x ** y, inspired by this comment. It works for 32-bit signed int.
For small values of y, it uses exponentiation by squaring. For large values of y, there are only a few values of x where the result doesn't overflow. This implementation uses a lookup table to read the result without calculating.
On overflow, the C standard permits any behavior, including crash. However, I decided to do bound-checking on LUT indices to prevent memory access violation, which could be surprising and undesirable.
Pseudo-code:
If `x` is between -2 and 2, use special-case formulas.
Otherwise, if `y` is between 0 and 8, use special-case formulas.
Otherwise:
Set x = abs(x); remember if x was negative
If x <= 10 and y <= 19:
Load precomputed result from a lookup table
Otherwise:
Set result to 0 (overflow)
If x was negative and y is odd, negate the result
C code:
#define POW9(x) x * x * x * x * x * x * x * x * x
#define POW10(x) POW9(x) * x
#define POW11(x) POW10(x) * x
#define POW12(x) POW11(x) * x
#define POW13(x) POW12(x) * x
#define POW14(x) POW13(x) * x
#define POW15(x) POW14(x) * x
#define POW16(x) POW15(x) * x
#define POW17(x) POW16(x) * x
#define POW18(x) POW17(x) * x
#define POW19(x) POW18(x) * x
int mypow(int x, unsigned y)
{
static int table[8][11] = {
{POW9(3), POW10(3), POW11(3), POW12(3), POW13(3), POW14(3), POW15(3), POW16(3), POW17(3), POW18(3), POW19(3)},
{POW9(4), POW10(4), POW11(4), POW12(4), POW13(4), POW14(4), POW15(4), 0, 0, 0, 0},
{POW9(5), POW10(5), POW11(5), POW12(5), POW13(5), 0, 0, 0, 0, 0, 0},
{POW9(6), POW10(6), POW11(6), 0, 0, 0, 0, 0, 0, 0, 0},
{POW9(7), POW10(7), POW11(7), 0, 0, 0, 0, 0, 0, 0, 0},
{POW9(8), POW10(8), 0, 0, 0, 0, 0, 0, 0, 0, 0},
{POW9(9), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{POW9(10), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
int is_neg;
int r;
switch (x)
{
case 0:
return y == 0 ? 1 : 0;
case 1:
return 1;
case -1:
return y % 2 == 0 ? 1 : -1;
case 2:
return 1 << y;
case -2:
return (y % 2 == 0 ? 1 : -1) << y;
default:
switch (y)
{
case 0:
return 1;
case 1:
return x;
case 2:
return x * x;
case 3:
return x * x * x;
case 4:
r = x * x;
return r * r;
case 5:
r = x * x;
return r * r * x;
case 6:
r = x * x;
return r * r * r;
case 7:
r = x * x;
return r * r * r * x;
case 8:
r = x * x;
r = r * r;
return r * r;
default:
is_neg = x < 0;
if (is_neg)
x = -x;
if (x <= 10 && y <= 19)
r = table[x - 3][y - 9];
else
r = 0;
if (is_neg && y % 2 == 1)
r = -r;
return r;
}
}
}
My case is a little different, I'm trying to create a mask from a power, but I thought I'd share the solution I found anyway.
Obviously, it only works for powers of 2.
Mask1 = 1 << (Exponent - 1);
Mask2 = Mask1 - 1;
return Mask1 + Mask2;
In case you know the exponent (and it is an integer) at compile-time, you can use templates to unroll the loop. This can be made more efficient, but I wanted to demonstrate the basic principle here:
#include <iostream>
template<unsigned long N>
unsigned long inline exp_unroll(unsigned base) {
return base * exp_unroll<N-1>(base);
}
We terminate the recursion using a template specialization:
template<>
unsigned long inline exp_unroll<1>(unsigned base) {
return base;
}
The exponent needs to be known at runtime,
int main(int argc, char * argv[]) {
std::cout << argv[1] <<"**5= " << exp_unroll<5>(atoi(argv[1])) << ;std::endl;
}
I've noticed something strange about the standard exponential squaring algorithm with gnu-GMP :
I implemented 2 nearly-identical functions - a power-modulo function using the most vanilla binary exponential squaring algorithm,
labeled ______2()
then another one basically the same concept, but re-mapped to dividing by 10 at each round instead of dividing by 2,
labeled ______10()
.
( time ( jot - 1456 9999999999 6671 | pvE0 |
gawk -Mbe '
function ______10(_, __, ___, ____, _____, _______) {
__ = +__
____ = (____+=_____=____^= \
(_ %=___=+___)<_)+____++^____—
while (__) {
if (_______= __%____) {
if (__==_______) {
return (_^__ *_____) %___
}
__-=_______
_____ = (_^_______*_____) %___
}
__/=____
_ = _^____%___
}
}
function ______2(_, __, ___, ____, _____) {
__=+__
____+=____=_____^=(_%=___=+___)<_
while (__) {
if (__ %____) {
if (__<____) {
return (_*_____) %___
}
_____ = (_____*_) %___
--__
}
__/=____
_= (_*_) %___
}
}
BEGIN {
OFMT = CONVFMT = "%.250g"
__ = (___=_^= FS=OFS= "=")(_<_)
_____ = __^(_=3)^--_ * ++_-(_+_)^_
______ = _^(_+_)-_ + _^!_
_______ = int(______*_____)
________ = 10 ^ 5 + 1
_________ = 8 ^ 4 * 2 - 1
}
GNU Awk 5.1.1, API: 3.1 (GNU MPFR 4.1.0, GNU MP 6.2.1)
.
($++NF = ______10(_=$___, NR %________ +_________,_______*(_-11))) ^!___'
out9: 48.4MiB 0:00:08 [6.02MiB/s] [6.02MiB/s] [ <=> ]
in0: 15.6MiB 0:00:08 [1.95MiB/s] [1.95MiB/s] [ <=> ]
( jot - 1456 9999999999 6671 | pvE 0.1 in0 | gawk -Mbe ; )
8.31s user 0.06s system 103% cpu 8.058 total
ffa16aa937b7beca66a173ccbf8e1e12 stdin
($++NF = ______2(_=$___, NR %________ +_________,_______*(_-11))) ^!___'
out9: 48.4MiB 0:00:12 [3.78MiB/s] [3.78MiB/s] [<=> ]
in0: 15.6MiB 0:00:12 [1.22MiB/s] [1.22MiB/s] [ <=> ]
( jot - 1456 9999999999 6671 | pvE 0.1 in0 | gawk -Mbe ; )
13.05s user 0.07s system 102% cpu 12.821 total
ffa16aa937b7beca66a173ccbf8e1e12 stdin
For reasons extremely counter-intuitive and unknown to me, for a wide variety of inputs i threw at it, the div-10 variant is nearly always faster. It's the matching of hashes between the 2 that made it truly baffling, despite computers obviously not being built in and for a base-10 paradigm.
Am I missing something critical or obvious in the code/approach that might be skewing the results in a confounding manner ? Thanks.