Write a C program that counts the number of 1s in the binary representation of an unsigned integer value (4 bytes)
Solution 1
Your count
variable is not initialized, so it could start from any value at random1. Always initialized your variables:
int count = 0;
Then when you print it, you print the wrong thing - a pointer to count rather than the count itself, and without a carriage return, so you get it all on a line: if the numbers were correct you'd get a single issue of "12345" or "11122234445".
printf("Count is now is %d\n", count);
I'd strongly suggest you turn on all warnings from your compiler - this would have warned you of an uninitialized variable and almost certainly of the difference between the %d and what was fed to it (and maybe too the fact you're missing includes for printf
)
1 perversely, in some controlled development environment memory is zeroed and you'd see no bug. Then you would okay the program for production. The program would run in a performance optimized environment where memory zeroing isn't worth the trouble. And there the program would start consistently failing. Since you're beginning, you don't want to pick up bad habits.
Solution 2
There are problems in your code:
- you should not read the number as a
float
, you loose precision for numbers larger than 23 bits. -
count
is uninitialized. Even just incrementing it has undefined behavior. - you should print the number of bits with
printf("%d\n", count);
after the end of the loop. You currently print the address ofcount
with an invalid conversion specifier for this type.
Here is a corrected version:
#include <stdio.h>
int main(void) {
unsigned int num;
printf("Please enter an integer: ");
if (scanf("%u", &num) == 1) {
int count = 0;
while (num > 0) {
count += num & 1;
num >>= 1;
}
printf("%d\n", count);
} else {
printf("Warning: this is not a valid integer\n");
}
return 0;
}
Notes:
- The program is limited to numbers below
UINT_MAX
, typically4294967295
on current systems. Larger numbers will be handled in an implementation defined way. - There are more sophisticated ways to count the number of 1 bits in an integers. You can learn about these here: https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
Related videos on Youtube
Comments
-
Frankie_C almost 2 years
I'm trying to write a C program that will count all of the number of 1s in any binary representation of an integer that the user chooses and inputs. Then I want to print the total number of 1s. But first, I have to check to make sure the inputed number is an integer. My code:
#include <stdio.h> int main() { int num; int count; float input; printf("Please enter an integer: "); scanf("%f", &input); num = (int)input; if (num == input) { while (num > 0) { count += num & 1; num >>= 1; printf("%d", &count); } } else { printf("Warning: this is not a valid integer."); } return 0; }
When I run the code, I'm able to enter my integer of choice, but then I'm getting an output that says:
134148802013414880201341488020
, or something similar. I've only recently started coding with C, so I'm not sure what this means or where my code is going wrong.-
chux - Reinstate Monica over 6 yearsSuggest to use
unsigned u; scanf("%u", &u);
and then count the1
s inu
. -
chux - Reinstate Monica over 6 years
int count; ...printf("%d", &count);
should generate a compiler warning. Save time vs posting on SO. Enable all compiler warnings to see code is attempting to print the address ofcount
and not the value ofcount
. -
axiac over 6 years@Frankie_C what is C++ in this code?
-
Gene over 6 years
%f
is definitely wrong. Use%u
as @chux said -
Frankie_C over 6 years@axiac Sorry confused threads. I was supposed to correct another thread. Put back.
-
-
Admin over 6 yearsYou're right, I overlooked initializing my count. I also think my print statement should be outside of my while loop. Thanks!
-
Admin over 6 yearsOne quick question: decimal numbers shouldn't be accepted, I think, but when I test the code with a decimal like 7.6, I receive an output instead of my custom warning. Why is that?
-
Costantino Grana over 6 yearsWell, if you want to mention "more sophisticated ways", is worth mentioning that all modern processors/compilers have some flavor of
popcnt()
which inevitably takes incredibly less than any other trick we can come up with. Check out en.wikipedia.org/wiki/Intrinsic_function -
chqrlie over 6 years@GarrettMcClure:
7.6
is parsed byscanf("%u"
as the integer7
followed by other characters (.6
) which are left in the input stream. It is cumbersome to usescanf()
to perform precise input validation. -
chqrlie over 6 years@CostantinoGrana: good point. I have heard that some sophisticated C compilers actually detect naive bit counting algorithms and produce optimal code with
popcnt
or equivalent opcodes. This would be the best approach to optimisation as it favors simplicity and portability at the source level.