2

Basically all I'm trying to do is run a loop that returns the value of X/Y Mod 10 where X is 1234567890123456 and Y is 10^i, so that I can get each individual digit of 1234567890123456 separated. But after i = 7 it returns 11 instead of the correct value (9). All numbers involved are of the long data type. I've tried doing it with the pow() function, and manually by just inputting the powers of ten and still get the same result.

#include <stdio.h>
#include <math.h>
long Cardno;
long Digits;
long Divider;
int main(void)
{
    Cardno = 1234567890123456;
    Digits = log10(Cardno) +1;

    if (Digits == 13 || Digits == 15 || Digits == 16)
    {
        for(int i = 0; i <= Digits; i++)
    {
       printf("%lo\n", Cardno/10000000 % 10);
    }
    }
    else
    {
        printf("INVALID\n");
    }
}
SirGarde
  • 21
  • 2
  • 3
    That number can't fit in a long, try unsigned long long. And append ULL to the end of your literal. Also, log10 expects double. Enable warnings when compiling '-Wall -Wextra' and you should get compilation errors. – Fredrik Aug 30 '22 at 06:58
  • Changing it to an unsigned long long fixed the problem, I think my bad at math brain didn't realize how large the number I was actually dealing with was. Thank you. – SirGarde Aug 30 '22 at 07:08
  • 3
    General rule: Card numbers (and phone numbers) should not be considered to be integers but strings. – Gerhardh Aug 30 '22 at 07:28
  • @Gerhardh Hear, hear!! When it comes time to do the checksum (left to right) the even/odd lengths (15 v. 16) will inspire some off-the-wall recursive function!!! Heaven help us all! `:)` – Fe2O3 Aug 30 '22 at 07:33
  • @Gerhardh how would you do the checksum calculation on a string? – SirGarde Aug 30 '22 at 07:39
  • If you have a string `char str[17]="0123...567";` You can access each single character using `str[i]` and to get from the character `'1'` to the value `1` you simply need to do `str[i]-'0'`. No need to do tons of divisions to get each digit. – Gerhardh Aug 30 '22 at 07:44
  • 1
    @Gerhardh okay yeah that's significantly easier. Thank you. – SirGarde Aug 30 '22 at 07:50
  • It also has advantage that you can handle leading zeros which is impossible for integers. And it works also for "numbers" that are too long for any integer type on your system. – Gerhardh Aug 30 '22 at 07:53
  • Does this answer your question? [How do I mute this error : "integer literal is too large to be represented in a signed integer type"](https://stackoverflow.com/questions/35136202/how-do-i-mute-this-error-integer-literal-is-too-large-to-be-represented-in-a) – Karl Knechtel Aug 30 '22 at 09:08

1 Answers1

2

so you have to use long long instead of long , I don't why the compiler didn't give this warning , but the compiler of mine gave me this warning :

Implicit conversion from 'long long' to 'long' changes value from 1234567890123456 to 1015724736

also variable called Digits doesn't need to be long , int will work just fine. also , function called log10() takes double and returns double so you have to cast that.

also in your code you are printing Cardno/10000000 % 10 which is wrong , it sould be (Cardno/ (long long )pow(10, i)) % 10

and here is the full code :

#include <stdio.h>
#include <math.h>
long long Cardno;
int Digits;
long long Divider;
int main(void)
{
    Cardno = 1234567890123456;
    Digits = (int)log10((double )Cardno) +1;

    if (Digits == 13 || Digits == 15 || Digits == 16)
    {
        for(int i = 0; i <= Digits; i++)
        {
            printf("%ld\n",(Cardno/ (long long )pow(10, i)) % 10);
        }
    }
    else
    {
        printf("INVALID\n");
    }
}
abdo Salm
  • 1,678
  • 4
  • 12
  • 22
  • The casts in the call to `log10()` are not necessary because the compiler has the necessary information to apply them automatically — including `` deals with them. That said, they are not completely pointless. But it is probably better to determine the number of digits using repeated integer division rather than using floating-point arithmetic. – Jonathan Leffler Aug 30 '22 at 11:35