pythoncalgorithmlong-integerluhn

Challenge of Translating Python Code to C: Implementing Luhn Algorithm for Checksum Calculation


I'm currently working on implementing the Luhn algorithm in C for checksum calculation. However, I encountered an issue with my C code where it consistently produces incorrect output (giving 11 instead of the expected 29). Frustrated by this, I decided to rewrite the algorithm in Python, which surprisingly worked flawlessly within just 2 minutes. I'm now puzzled about what might be causing the discrepancy between the C and Python implementations. Could someone please lend a hand in reviewing my C code and help identify the underlying issue? Below are both implementations for comparison:

x = 4003600000000014

def checkSum(n):
    sm = 0
    swm = 0
    j = 10
    k = 100
    l = 100
    m = 1000
    for i in range(0, len(str(n)) // 2):
        sm += (((n % k) - (n % j)) // j)*2
        j *= 100
        k *= 100
    swm += n % 10
    for i in range(0, len(str(n)) // 2):
        swm += ((n % m) - (n % l)) // l
        l *= 100
        m *= 100
    return sm+swm

print(checkSum(x))

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int checkSum(long n);
int longLength(long n);

int main(void)
{
    long long number = 4003600000000014;
    printf("%d\n", checkSum(number));
    return 0;
}

int longLength(long n)
{
    int length = 0;
    while (n > 0)
    {
        n = n/10;
        length++;
    }
    return length;
}

int checkSum(long n)
{
    int sm = 0;
    int swm = 0;
    int j = 10;
    int k = 100;
    int l = 100;
    int m = 1000;

    for(int i=0;i<longLength(n)/2;i++)
    {
        sm += (((n % k)-(n % j))/j)*2;
        j *= 100;
        k *= 100;
    }
    swm+= n % 10;
    for(int i=0 ;i<longLength(n)/2;i++)
    {
        swm +=(((n % m)-(n % l))/l);
        l *= 100;
        m *= 100;
    }
    return sm + swm;
}


Solution

  • A long number is possibly narrower than a long long.

    Use a wider argument in the declaration and definition to not lose information.

    // int longLength(long n);
    int longLength(long long n);
    // int checkSum(long n);
    int checkSum(long long n);
    
    
    // int longLength(long n)
    int longLength(long long n)
      ...
    
    // int checkSum(long n) 
    int checkSum(long long n)
      ...
    

    Save time and enable all compiler warnings to receive something like:

    warning: conversion from 'long long int' to 'long int' may change value [-Wconversion]
    

    This will indicate many of the int variables should be long long.

    // warning: conversion from 'long int' to 'int' may change value [-Wconversion]
    sm += (((n % k) - (n % j)) / j) * 2;