Reputation: 39
I am trying to test if a number is even or odd.
It works fine with numbers of 8 digits, but when ever I go over 9 digits it looks weird. The number I type in changes.
Example with 8 digits:
Enter the ID : 20202020
20202020 is even.
Program ended with exit code: 0
But when doing it with 10 digits it looks like this:
Enter an integer: 2345678915
-1949288381 is odd.
Program ended with exit code: 0
// these nr that are different, what are they?
//Have not found any info about it either...
Code:
#include <stdio.h>
int main()
{
int id;
printf("Enter the Id: ");
scanf("%d", &id);
if(id % 2 == 0)
printf("%d is even.\n", id);
else
printf("%d is odd.\n", id);
return 0;
}
I tried changing it to double, does not help.
Does it have anything to do with the if statement?
if(id % 2 == 0)
Upvotes: 0
Views: 813
Reputation: 11219
This problem comes from the fact that, as everybody mentionned, you are trying to fit more information that what can be contained in a signed (32 bits) integer.
Nevertheless I feel that other answers are just kicking the can down the road, so I will provide you a solution that would also work for a REALLY high (odd and even) number (up to BUFFER_SIZE digits...):
#include <stdio.h>
#define BUFFER_SIZE 1024
int main(int argc, char **argv) {
if (argc < 2)
return 1;
char buffer[BUFFER_SIZE + 1];
printf("Enter the Id: ");
fgets(buffer, BUFFER_SIZE, stdin);
unsigned len = strlen(buffer);
buffer[len -1] = '\0'; // remove '\n' from fgets
// you might want to check that the user input a valid number
// https://stackoverflow.com/questions/16644906/how-to-check-if-a-string-is-a-number
int id = buffer[len - 2] - '0'; // get last digit
if(id % 2 == 0)
printf("%s is even.\n", buffer);
else
printf("%s is odd.\n", buffer);
return 0;
}
output:
Enter the Id: 6734863486834863486348648564386803486438683456438658438764568435864783
6734863486834863486348648564386803486438683456438658438764568435864783 is odd.
Upvotes: 2
Reputation: 75062
Typical int
(signed 32-bit long) can store only upto 2,147,483,647. Your input 2345678915
is beyond this.
If this is supported in your environment, you can use long long
, which is typically 64-bit long and can store upto 9,223,372,036,854,775,807.
#include <stdio.h>
int main()
{
long long id;
printf("Enter the Id: ");
scanf("%lld", &id);
if(id % 2 == 0)
printf("%lld is even.\n", id);
else
printf("%lld is odd.\n", id);
return 0;
}
Another option is using int64_t
, which may be supported in wider environments.
#include <stdio.h>
#include <inttypes.h>
int main()
{
int64_t id;
printf("Enter the Id: ");
scanf("%" SCNd64, &id);
if(id % 2 == 0)
printf("%" PRId64 " is even.\n", id);
else
printf("%" PRId64 " is odd.\n", id);
return 0;
}
Being inspired from @0___________, you can judge if a number is even or odd by just seeing the last digit.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
{
int input;
int is_valid_number = 1;
size_t input_len = 0;
char* id = malloc(1);
if (id == NULL) {
perror("malloc");
return 1;
}
printf("Enter the Id: ");
/* read the first line */
while ((input = getchar()) != '\n' && input != EOF) {
char* next_id = realloc(id, input_len + 2); /* +1 for new character and +1 for NUL */
if (next_id == NULL) {
perror("realloc");
free(id);
return 1;
}
/* check if the input correctly represents a number */
is_valid_number = is_valid_number && (isdigit(input) || (input_len == 0 && input == '-'));
/* store this digit */
id = next_id;
id[input_len++] = (char)input;
}
id[input_len] = '\0';
if (input_len == 0 || !is_valid_number)
printf("%s is not a number.\n", id);
else if((id[input_len - 1] - '0') % 2 == 0)
printf("%s is even.\n", id);
else
printf("%s is odd.\n", id);
free(id);
return 0;
}
Upvotes: 0
Reputation: 67476
As your program just checks if the entered number is even or odd. It does not have to be stored anywhere so there is no need to convert it to any integer type. We only care if the last digit can be divided by two or not.
Max length of the integer is defined by MAXINTEGERLENGHT
#define MAXINTEGERLENGHT (1000000LU)
int AND(const char *str)
{
const static char DIGITS[] = "01234567890";
const char *wrk = str;
const char *lastpos;
int result = -1;
if(wrk && *wrk)
{
result = 0;
while(*wrk)
{
if(!(lastpos = strchr(DIGITS, *wrk++)))
{
result = -1;
break;
}
}
if(result != -1)
result = (lastpos - DIGITS) & 1;
}
return result;
}
int main(void)
{
char number[MAXINTEGERLENGHT];
fgets(number, sizeof(number), stdin);
number[strlen(number) - 1] = 0;
switch(AND(number))
{
case -1:
printf("%s is invalid\n", number);
break;
case 1:
printf("%s is odd\n", number);
break;
case 0:
printf("%s is even\n", number);
break;
}
}
And as an example very long result:
x86-64 gcc 10.2
Program returned: 0
Program stdout
465954328762383465734826523743653247234684327563474368743634784368754386565465634623456435457656735643565465465645455445654543424536565434535464564564564564564564564564565464564564564556546564545643563456 is even
Upvotes: 0
Reputation: 895
The problem is not in the modulo operation, but in the type of data you are using.
Your id number is an int
, which is (in this case) formed with 32 bits. This means that the maximum number you can use is 2,147,483,647
, and you are using a bigger number.
You should try using long
, or a number type that uses more than 32 bits, like long long
. This means that the maximum number you can use is 263 - 1 = 9,223,372,036,854,775,807
, solving your problem.
So, you should make these changes in your code:
long long id;
printf("Enter the Id: ");
scanf("%lld", &id);
This Page provides a good explanation of the types available in C++.
Upvotes: 5