int main()
{
double hexa_number;
double bitmask = 0x80;
double i;
printf("Enter 8 bit number in hexadecimal form: ");
scanf("%lf",& hexa_number);
for( i = 0; i <= 8; i++)
{
if(hexa_number&(bitmask >> i))
printf("1");
else
printf("0");
}
return 0;
}
plus Displaying the binary representation of this number,
along with a count of the number of 0’s and 1’s in the binary number.
i found other ways to convert it but not with bitmask
The problem could be that you are using a double for your bitmask. I don't think >> makes much sense for doubles especially as they are composed of a sign bit, mantissa and 2^ exponent.
For example, 8 >> 1 is 4. That is a nice consistent operation, same as division by 2.
If we imagine an unsigned two byte float for simplicity and imagine that the first byte represents the mantissa and the second the exponent (both unsigned), then 7 * 2^4 (=112) could be represented as 0b00000111 00000100. If you shift that 1 to the right, >> 1, you will get 0b00000011 10000010, which by our convention is now 3 * 2^130. This is definitely not the division by 2 you would get by shifting an integer right by 1.
My compiler gives "error: invalid operands to binary >> (have double and unsigned)" if I try bitwise shifting a floating point number.
So basically you could try the following:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int hexa_number = 0;
unsigned num_bits = sizeof(int)*8;
unsigned bitmask = 1 << (num_bits - 1);
printf("Enter a number in hexadecimal form: ");
scanf("%i", &hexa_number);
unsigned k = 0;
unsigned num_ones = 0;
unsigned num_zeros = 0;
for(k = 0; k != num_bits; k ++)
{
if(hexa_number & (bitmask >> k))
{
printf("1");
num_ones ++;
}
else
{
printf("0");
num_zeros++;
}
}
printf("\nNumber of ones is %i\nNumber of zeros is %i", num_ones, num_zeros);
return 0;
}
Related
I tried left-shifting a 32-bit integer by 24:
char *int_to_bin(int num) {
int i = 0;
static char bin[64];
while (num != 0) {
bin[i] = num % 2 + 48;
num /= 2;
i++;
}
bin[i] = '\0';
return (bin);
}
int main() {
int number = 255;
printf("number: %s\n", int_to_bin(number));
printf("shifted number: %s\n", int_to_bin(number << 24));
return 0;
}
OUTPUT:
number: 11111111
shifted number: 000000000000000000000000/
and i left-shift with 23-bit it yields this result:
0000000000000000000000011111111
Well Why is it like that and what's the matter with '/' at the end of the wrong result?
Two things:
If number has the value 255 then number << 24 has the numerical value 4278190080, which overflows a 32-bit signed integer whose largest possible value is 2147483647. Signed integer overflow is undefined behavior in C, so the result could be anything at all.
What probably happens in this case is that the result of the shift is negative. When num is negative then num % 2 may take the value -1, so you store character 47 in the string, which is /.
Bit shifting math is usually better to do with unsigned types, where overflow is well-defined (it wraps around and bits just shift off the left and vanish) and num % 2 can only be 0 or 1. (Or write num & 1 instead.)
Your int_to_bin routine puts the least-significant bits at the beginning of the string (on the left), so the result is backwards from the way people usually write numbers (with the least-significant bits on the right). You may want to rewrite it.
Shift works fine, you simply print it from the wrong direction.
char *int_to_bin(char *buff, int num)
{
unsigned mask = 1U << (CHAR_BIT * sizeof(num) - 1);
char *wrk = buff;
for(; mask; mask >>= 1)
{
*wrk++ = '0' + !!((unsigned)num & mask);
}
*wrk = 0;
return buff;
}
int main()
{
char buff[CHAR_BIT * sizeof(int) + 1];
int number = 255;
printf("number: %s\n", int_to_bin(buff, number));
printf("shifted number: %s\n", int_to_bin(buff, number << 24));
return 0;
}
Shifting signed integers left is OK, but the right shift is implementation-defined. Many systems use arithmetic shift right and the result is not the same as using the bitwise one:
https://godbolt.org/z/e7f3shxd4
you are storing numbers backwards
you are using signed int32 while shifting by 23 results needs more than 32 bits to handle that operation ...you should use long long int
signed integer can lead to wrong answers as 1<<31 is -1 which results in bad characters in string
finally using unsigned long long int with storing numbers in correct order will produce correct string
you should try re write code on your own before seeing this improved version of your code
#include<stdio.h>
#include<stdlib.h>
char *int_to_bin( unsigned long long int num) {
int i = 0;
static char bin[65];
while (i != 64) {
bin[63-i] = num % 2 + 48;
num /= 2;
i++;
}
bin[64] = '\0';
return (bin);
}
int main() {
unsigned long long int number = 255;
printf("number 1: %s\n", int_to_bin(number));
printf("number 2: %s\n", int_to_bin(number << 24));
return 0;
}
I want to print the bits of a float number.
My plan was to:
Discover how many bits there are at all
Create and int array and insert into it the bits of the number using simple right bits shifting.
Because the bits were inserted in a reversed order to what I need, lets run another loop to go over the array one again but this time, from the last element to the first one.
Why?
Lets take for example the number 4.2:
I believe the bits were entered in the following way:
4 - 1000
2 - 0010
So together it's 10000010.
Enters FILO - First in -> Last out.
So 0 will be the first element but as you cans see here, we need it in the end.
Here is my code:
float FloatAnalysis(float number)
{
int arr[32] = {0};
float num_cpy = number;
size_t num_of_bits = 0, i = 0;
while (0 != number)
{
num_cpy >>= 1;
++num_of_bits;
}
num_cpy = number;
for(i = 0; i < num_of_bits; ++i)
{
arr[i] = (num_cpy & 1);
num_cpy >>= 1;
}
for(i = num_of_bits-1; i => 0; --i)
{
printf("%d", arr[i]);
}
}
And here the output:
bitwise.c:359:11: error: invalid operands to binary >> (have ‘float’ and ‘int’)
359 | num_cpy >>= 1;
| ^~~
bitwise.c:368:21: error: invalid operands to binary & (have ‘float’ and ‘int’)
368 | arr[i] = (num_cpy & 1);
| ^
bitwise.c:369:11: error: invalid operands to binary >> (have ‘float’ and ‘int’)
369 | num_cpy >>= 1;
| ^~~
Can you expl
ain me what is going on here?
Use memcpy
You cannot perform bitwise operations on a float.
You can use memcpy to copy your float to an unsigned int and preserves its bits:
float num_cpy = number;
becomes
unsigned int num_cpy;
memcpy(&num_cpy, &number, sizeof(unsigned));
Note that if you try to cast the result, by taking your float address in memory and cast it as unsigned, with:
num_cpy = *(float *)&number;
You will strip the floating point part away, you will preserve the value (or what can be preserved) but loose the accuracy of its binary representation.
Example
In the below example,
float number = 42.42;
unsigned int num_cpy;
memcpy(&num_cpy, &number, sizeof(unsigned));
unsigned int num_cpy2 = *(float *)&number;
printf("Bits in num_cpy: %d bits in num_cpy2: %d\n", __builtin_popcount(num_cpy), __builtin_popcount(num_cpy2));
printf("%d\n", num_cpy);
printf("%d\n", num_cpy2);
will output
Bits in num_cpy: 12 bits in num_cpy2: 3
1110027796 // memcpy
42 // cast
More reading
I recommend that you especially take a look at floating point internal representation that sums up very well what is going at the bits level.
Internal Representation: sign: 1 bit, exponent: 8 bits, fraction: 23 bits
(for a single precision, 32 bits floating point, that we call float in C)
OP's code has various problems aside from compiler error.
i => 0 is not proprer code. Perhaps OP wanted i >= 0?. Even that has trouble.
size_t num_of_bits = 0, i = 0;
...
// Bug: i => 0 is always true as `i` is an unsigned type.
for(i = num_of_bits-1; i >= 0; --i) {
printf("%d", arr[i]);
}
OP's repaired code.
float FloatAnalysis(float number) {
assert(sizeof(float) == sizeof(unsigned));
int arr[32] = {0};
//float num_cpy = number;
unsigned num_cpy;
memcpy(&num_cpy, &number, sizeof num_cpy); // copy the bit pattern to an unsigned
// size_t num_of_bits = 0, i = 0;
size_t num_of_bits = 32, i = 0; // Always print 32 bits
//while (0 != number) {
// num_cpy >>= 1;
// ++num_of_bits;
//}
//num_cpy = number;
for (i = 0; i < num_of_bits; ++i) {
arr[i] = (num_cpy & 1);
num_cpy >>= 1;
}
// for(i = num_of_bits-1; i => 0; --i)
for (i = num_of_bits; i-- > 0; ) { // Change test condition
printf("%d", arr[i]);
}
printf("\n");
// Some more output
// 12345678901234567890123456789012
printf("sEeeeeeeeMmmmmmmmmmmmmmmmmmmmmmm\n");
printf("%a\n", number);
return number;
}
int main() {
FloatAnalysis(4.2f);
}
Output
01000000100001100110011001100110
sEeeeeeeeMmmmmmmmmmmmmmmmmmmmmmm
0x1.0cccccp+2
Below C program display binary representation of inputted decimal number:
#include <stdio.h>
#include <stdlib.h>
typedef union {
int i;
struct {
unsigned int dgts: 31;
unsigned int sign: 1;
} bin;
} myint;
void printb(int n, int i) {
int k;
for (k = i - 1; k >= 0; k--)
if ((n >> k) & 1)
printf("1");
else
printf("0");
}
void display_binary(myint x) {
printf("%d | ", x.bin.sign);
printb(x.bin.dgts, 31);
printf("\n");
}
int main() {
myint decimal;
printf("input decimal value : ");
scanf("%d", &decimal.i);
printf("Binary representation is:\n");
display_binary(decimal);
return 0;
}
The program is working correctly. What I can't understand is order of dgts and sign members of bin struct. Intuitively, sign member should precede dgts as bits that representing data are ordered from left to write in memory (as far as I know). After swapping orders of these two members, result became false. Why dgts should come before sign?
order of bits in the bitfields is implementation-defined, but most popular compilers start with LSB.
Numbers are stored binary and it does not matter how you enter them. Negative numbers are stored as two'2 complement on most modern systems. In this system, the sign bit does not exist "per se". No special types are needed
I would implement it as
void printb(int n) {
unsigned int mask = 1U << (sizeof(n) * CHAR_BIT - 1);
for (; mask; mask >>= 1)
{
printf("%c", (n & mask) ? '1' : '0');
}
}
How would I write code in C to assign a decimal number's binary representation to a char variable?
\\ x is the value of the decimal integer
\\ y is length of the binary representation
{
binary[33] = {0};
while(x!=0){
binary[y] = (x%2)+'0';
y--;
x/=2;
}
}
The idea of scanning bits in number is to start with MSB bit of input number and to proceed to the LSB bit. When first 1 is detected, start printing/saving/whatever, even if 0 is later detected.
This is now example, which will print bits of your number, starting to print when it reaches first 1.
#include <stdio.h>
#include "limits.h"
int main() {
unsigned int num = 10;
int y = 0, i;
for (i = sizeof(num) * CHAR_BIT - 1; i >= 0; i--) {
if (num & (1U << i)) {
printf("1");
y++;
} else if (y) {
printf("0");
y++;
}
}
printf("\n");
return 0;
}
Output for num = 10: 1010
If you want to store your result to array, replace printf statements with something similar to: outputBuffer[y] = '1' or '0'
#include <stdio.h>
int NumberOfSetBits(int);
int main(int argc, char *argv[]) {
int size_of_int = sizeof(int);
int total_bit_size = size_of_int * 8;
// binary representation of 3 is 0000011
// C standard doesn't support binary representation directly
int n = 3;
int count = NumberOfSetBits(n);
printf("Number of set bits is: %d\n", count);
printf("Number of unset bits is: %d", total_bit_size - count);
}
int NumberOfSetBits(int x)
{
int count = 0;
//printf("x is: %d\n", x);
while (x != 0) {
//printf("%d\n", x);
count += (x & 1);
x = x >> 1;
}
return count;
}
Number of set bits is: 2
Number of unset bits is: 30
int size_of_int = sizeof(int);
int total_bit_size = size_of_int * 8;
^ that will get the size of the int on the system and times it by 8 which is the number of bits in each byte
EDITED: Without the use of the ~
/*
Calculate how many set bits and unset bits are in a binary number aka how many 1s and 0s in a binary number
*/
#include <stdio.h>
unsigned int NumberOfSetBits(unsigned int);
unsigned int NumberOfUnSetBits(unsigned int x);
int main() {
// binary representation of 3 is 0000011
// C standard doesn't support binary representation directly
unsigned int n = 3;
printf("Number of set bits is: %u\n", NumberOfSetBits(n));
printf("Number of unset bits is: %u", NumberOfUnSetBits(n));
return 0;
}
unsigned int NumberOfSetBits(unsigned int x) {
// counts the number of 1s
unsigned int count = 0;
while (x != 0) {
count += (x & 1);
// moves to the next bit
x = x >> 1;
}
return count;
}
unsigned int NumberOfUnSetBits(unsigned int x) {
// counts the number of 0s
unsigned int count = 0;
while(x != 0) {
if ((x & 1) == 0) {
count++;
}
// moves to the next bit
x = x >> 1;
}
return count;
}
returns for input 3
Number of set bits is: 2
Number of unset bits is: 0
unset bits is 0? Doesn't seem right?
if I use NumberOfSetBits(~n) it returns 30
You've got a problem on some systems because you right shift a signed integer in your bit-counting function, which may shift 1's into the MSB each time for negative integers.
Use unsigned int (or just unsigned) instead:
int NumberOfSetBits(unsigned x)
{
int count = 0;
//printf("x is: %d\n", x);
while (x != 0) {
//printf("%d\n", x);
count += (x & 1);
x >>= 1;
}
return count;
}
If you fix that part of the problem, you can solve the other with:
int nbits = NumberOfSetBits(~n);
where ~ bitwise inverts the value in n, and hence the 'set bit count' counts the bits that were zeros.
There are also faster algorithms for counting the number of bits set: see Bit Twiddling Hacks.
To solve the NumberOfSetBits(int x) version without assuming 2's complement nor absence of padding bits is a challenge.
#Jonathan Leffler has the right approach: use unsigned. - Just thought I'd try a generic int one.
The x > 0, OP's code work fine
int NumberOfSetBits_Positive(int x) {
int count = 0;
while (x != 0) {
count += (x & 1);
x = x >> 1;
}
return count;
}
Use the following to find the bit width and not count padding bits.
BitWidth = NumberOfSetBits_Positive(INT_MAX) + 1;
With this, the count of 0 or 1 bits is trivial.
int NumberOfClearBits(int x) {
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits(x);
}
int NumberOfSetBits_Negative(int x) {
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits_Positive(~x);
}
All that is left is to find the number of bits set when x is 0. +0 is easy, the answer is 0, but -0 (1's compliment or sign magnitude) is BitWidth or 1.
int NumberOfSetBits(int x) {
if (x > 0) return NumberOfSetBits_Positive(x);
if (x < 0) return NumberOfSetBits_Negative(x);
// Code's assumption: Only 1 or 2 forms of 0.
/// There may be more because of padding.
int zero = 0;
// is x has same bit pattern as +0
if (memcmp(&x, &zero, sizeof x) == 0) return 0;
// Assume -0
return NumberOfSetBits_Positive(INT_MAX) + 1 - NumberOfSetBits_Positive(~x);
}
here is a proper way to count the number of zeores in a binary number
#include <stdio.h>
unsigned int binaryCount(unsigned int x)
{
unsigned int nb=0; // will count the number of zeores
if(x==0) //for the case zero we need to return 1
return 1;
while(x!=0)
{
if ((x & 1) == 0) // the condition for getting the most right bit in the number
{
nb++;
}
x=x>>1; // move to the next bit
}
return nb;
}
int main(int argc, char *argv[])
{
int x;
printf("input the number x:");
scanf("%d",&x);
printf("the number of 0 in the binary number of %d is %u \n",x,binaryCount(x));
return 0;
}