Convert string containing binary representation into number - C - c

I have a binary message on a string. The string contains values such as "10001000" and it's being used as a buffer to store binary representations of different data types. I will parse the data and then convert each sequence. My struggle is to convert an specific string of 1s and 0s into: integer, float or double. A possible solution for the int is strtol, but it doesn't solve all my problem...
I've read throw many discussions of people trying to create a string containing the binary representation of a number. But my issue is exactly the opposite: roll back the number once I have a string with it's binary representation.
Any thoughts or advices will be most welcome.

This is quite simple really...
unsigned int number;
char str[33];
int i;
int s;
/* Read some 32-bit binary number in character representation in str. */
Do some stuff.
/* Convert from string to binary. */
number = 0;
s = strlen(str);
for (i = 0; i < s; i++)
{
if (str[i] == 0x00) break;
if (str[i] == '0')
{
number |= 1;
number << 1;
}
if (str[i] == '1')
{
number &= 0xFFFFFFFE;
number << 1;
}
}
Generally, you can find this on Google or in your textbook. So you got this for free, this time.
EDIT:
I noticed that you also mentioned float or double as well. Those are complicated data types that are defined by the IEEE-754 standard. If the binary string is already in floating point representation, then you can just use a union to get from an unsigned int to one of the float types. Code below:
union float_conversion_t
{
unsigned int i[2];
float f;
double d;
};
Here you datafill one or both integers and then read the float or double value. You may need to adjust the size of the array depending on the word size of your machine (32-bit, 64-bit, or something else).

Thank you to Daniel and all other valid comments.
The main question was if float/double conversions were possible with any preexisting function. My understanding after all this (correct me plz if I'm wrong) is no.
So one must go trough the math and conversion for floating points (lots of documentation on IEEE 754 online...) and use strtol for integers. Fair enough.
It may be of help to others:
Here's a conversion of binary IEEE 754 as string to double
But if you look for converting something like "1001.1101" (binary point representation) to float, this guy did a nice job

Related

getting exponent of a floating number in c

Sorry if this is already been asked, and I've seen other way of extracting the exponent of a floating point number, however this is what is given to me:
unsigned f2i(float f)
{
union {
unsigned i;
float f;
} x;
x.i = 0;
x.f = f;
return x.i;
}
I'm having trouble understanding this union datatype, because shouldn't the return x.i at the end always make f2i return a 0?
Also, what application could this data type even be useful for? For example, say I have a function:
int getexponent(float f){
}
This function is supposed to get the exponent value of the floating point number with bias of 127. I've found many ways to make this possible, however how could I manipulate the f2i function to serve this purpose?
I appreciate any pointers!
Update!!
Wow, years later and this just seem trivial.
For those who may be interested, here is the function!
int getexponent(float f) {
unsigned f2u(float f);
unsigned int ui = (f2u(f)>>23) & 0xff ;//shift over by 23 and compare to 0xff to get the exponent with the bias
int bias = 127;//initialized bias
if(ui == 0) return 1-bias; // special case 0
else if(ui == 255) return 11111111; //special case infinity
return ui - bias;
}
I'm having trouble understanding this union datatype
The union data type is a way for a programmer to indicate that some variable can be one of a number of different types. The wording of the C11 standard is something like "a union contains at most one of its members". It is used for things like parameters that may be logically one thing or another. For example, an IP address might be an IPv4 address or an IPv6 address so you might define an address type as follows:
struct IpAddress
{
bool isIPv6;
union
{
uint8_t v4[4];
uint8_t v6[16];
} bytes;
}
And you would use it like this:
struct IpAddress address = // Something
if (address.isIPv6)
{
doSomeV6ThingWith(address.bytes.v6);
}
else
{
doSomeV4ThingWith(address.bytes.v4);
}
Historically, unions have also been used to get the bits of one type into an object of another type. This is because, in a union, the members all start at the same memory address. If I just do this:
float f = 3.0;
int i = f;
The compiler will insert code to convert a float to an integer, so the exponent will be lost. However, in
union
{
unsigned int i;
float f;
} x;
x.f = 3.0;
int i = x.i;
i now contains the exact bits that represent 3.0 in a float. Or at least you hope it does. There's nothing in the C standard that says float and unsigned int have to be the same size. There's also nothing in the C standard that mandates a particular representation for float (well, annex F says floats conform to IEC 60559 , but I don't know if that counts as part of the standard). So the above code is, at best, non portable.
To get the exponent of a float the portable way is the frexpf() function defined in math.h
how could I manipulate the f2i function to serve this purpose?
Let's make the assumption that a float is stored in IEC 60559 format in 32 bits which Wkipedia thinks is the same as IEEE 754. Let's also assume that integers are stored in little endian format.
union
{
uint32_t i;
float f;
} x;
x.f = someFloat;
uint32_t bits = x.i;
bits now contains the bit pattern of the floating point number. A single precision floating point number looks like this
SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
^ ^ ^
bit 31 bit 22 bit 0
Where S is the sign bit, E is an exponent bit, M is a mantissa bit.
So having got your int32_t you just need to do some shifting and masking:
uint32_t exponentWithBias = (bits >> 23) & 0xff;
Because it's a union it means that x.i and x.f have the same address, what this allows you to do is reinterpret one data type to another. In this scenario the union is first zeroed out by x.i = 0; and then filled with f. Then x.i is returned which is the integer representation of the float f. If you would then shift that value you would get the exponent of the original f because of the way a float is laid out in memory.
I'm having trouble understanding this union datatype, because shouldn't the return x.i at the end always make f2i return a 0?
The line x.i = 0; is a bit paranoid and shouldn't be necessary. Given that unsigned int and float are both 32 bits, the union creates a single chunk of 32 bits in memory, which you can access either as a float or as the pure binary representation of that float, which is what the unsigned is for. (It would have been better to use uint32_t.)
This means that the lines x.i = 0; and x.f = f; write to the very same memory area twice.
What you end up with after the function is the pure binary notation of the float. Parsing out the exponent or any other part from there is very much implementation-defined, since it depends on floating point format and endianess. How to represent FLOAT number in memory in C might be helpful.
That union type is strongly discouraged, as it is strongly architecture dependant and compiler implementation dependant.... both things make it almost impossible to determine a correct way to achieve the information you request.
There are portable ways of doing that, and all of them have to deal with the calculation of logarithm to the base ten. If you get the integer part of the log10(x) you'll get the number you want,
int power10 = (int)log10(x);
double log10(double x)
{
return log(x)/log(10.0);
}
will give you the exponent of 10 to raise to get the number to multiply the mantissa to get the number.... if you divide the original number by the last result, you'll get the mantissa.
Be careful, as the floating point numbers are normally internally stored in a power of two's basis, which means the exponent you get stored is not a power of ten, but a power of two.

create number 0 only using int in the C

#include <stdio.h>
struct real_num
{
int int_num;
int frac_num;
};
void main()
{
struct real_num num1;
printf("input the number : ");
scanf("%d.%d",&num1.int_num,&num1.frac_num):
printf("%d.%d",num1.int_num,num1.frac_num);
}
i input 12.012 but buffer save 12.12 i want a 012 but this buffer save 12
what should i do? i want a save 012 (using only int)
Numbers are a matter of arithmetic. 1, 01, 1.0, 1.000, 0x01, 1e0 all describe the same number: whichever representation you use has the same mathematical properties, and behaves identically in calculation (ignoring the matter of computer storage of numbers as int or float or double... which is again another matter entirely).
The representation of a number is a matter of sequences of characters, or strings. Representations of numbers can be formatted differently, and can be in different bases, but can't be calculated with directly by a computer. To store leading zeroes, you need a string, not an int.
You typically convert from number representation to number at input, and from number to number representation at output. You would achieve your stated desire by not converting from number representation to number at input, but leaving it as a string.
You don't want to store 012, you want to store 0.012.
The value 0.012 in binary is (approximately):
0.00000011000100100110111010010111b
..and the value 12.012 is (approximately):
110.00000011000100100110111010010111b
Note that 0.012 is impossible to store precisely in binary because it would consume an infinite number of bits; in the same way that 1/3 can't be written precisely in decimal (0.333333333.....) because you'd need an infinite number of digits.
Let's look at 12.012. In hex it's this:
0x0000000C.03126E97
This makes it easier to see how the number would be stored in a pair of 32-bit integers. The integer part in one 32-bit integer, and the fractional part in another 32-bit integer.
The first problem is that you're using signed 32-bit integers, which means that one of the bits of the fraction is wasted for a sign bit. Essentially, you're using a "sign + 31 bit integer + wasted bit + 31 bit fraction" fixed point format. It'd be easier and better to use an unsigned integer for the fractional bits.
The second problem is that standard C functions don't support fixed point formats. This means that you either have to write your own "string to fixed point" and "fixed point to string" conversion routines, or you have use C's floating point conversion routines and write your own "floating point to fixed point" and "fixed point to floating point" conversion routines.
Note that the latter is harder (floating point is messy), slower, and less precise (double floating point format only supports 53 bits of precision while you can store 62 bits of precision).
A fraction does not consists of a single integer. A fraction consists of 2 integers: numerator/denominator.
Code needs to keep track of width of the fraction input. Could use "%n" to record offset in scan.
#include <stdio.h>
struct real_number {
int ipart;
int num;
int den_pow10;
};
void main(void) {
struct real_number num1;
printf("input the number : ");
fflush(stdout);
int n1 = 0;
int n2 = 0;
scanf("%d.%n%d%n",&num1.ipart, &n1, &num1.num , &n2):
if (n2 == 0) {
fprintf(stderr, "bad input\n");
return -1;
}
num1.den_pow10 = n2 - n1;
printf("%d.%*0d",num1.ipart,num1.den_pow10, num1.frac_num);
return 0;
}
Input/Output
input the number : 12.00056
Result 12.00056

How would I convert a char array to a float and check its range?

I am building an application in Microsoft Visual Studio 2012 and I have a function that takes in a char array and is supposed to return a single-precision floating point number.
My function:
Token aa_func08(char lexeme[]){
Token t; /* floating point literal Token to be returned */
double temp; /* floating point value of character array */
temp = atof(lexeme); /* convert character array to floating point value */
if ((FLT_MAX - temp <= FLT_EPSILON) || (temp - FLT_MIN <= FLT_EPSILON)) /* floating point value is outside the accepted range */
return aa_table[ES](lexeme); /* return an error Token */
t.code = FPL_T; /* set Token code */
t.attribute.flt_value = (float)temp; /* set Token integer value to floating point literal value */
return t; /* return floating point literal Token */
}
I would like to check the float value compared to the maximum and minimum values for the float data type, and I also need to check the length of the char array.
The output I expect is the following:
If I pass in:
1.999999999999999911111111111111111111111111111111111111111111111111111111111111111
I expect to get: 2.000000
If I pass in:
999999999999999999999999999999999999999999999999999999999999999999999999999999999.0
I expect to get: 99999999999999999999
If I pass in:
0.00000000000000000000000000000000000000000000000000000000000000000000000000000000001
I expect to get: 0.000000000000000000
Does anybody know how I can achieve such results, or at least point me in the right direction? Thank you!
EDIT
For the first case, the result 2.000000 is represented by a 32-bit float. The other two results are simply the string lexeme being truncated to the first 20 characters. So to summarize, if the lexeme represents a valid float, it is represented as a float, but if lexeme represents an invalid float (out of range, missing numbers after decimal point, etc.) then the first 20 characters of lexeme are what I return (not an actual float).
You might want to give this a read: What Every Computer Scientist Should Know About Floating-Point Arithmetic
Specifically you are not going to get "99999999999999999999", or 20 digits of precision out of a float type (or even out of a double). Second depending on how you convert the values you are likely to get 1E-83 for "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000001". You might also want to take a look at IEEE Floading Point
Your examples do not match your goals, suggesting that one or the other will lead to disappointment. If you need to convert a string to a 32 bit float type you will need to stick to the limitations of that format. If you need the precision (and behavior) your examples describe you will likely need to write some sort of custom numeric type.
Looks like OP's goal is to check that the number fits in a float range by using a string to double conversion and then testing limits.
The limit tests are ineffective. Wrong use of FLT_EPSILON and FLT_MIN.
Suggest simply comparing the double to +/-FLT_MAX.
volatile double d = atof(lexeme);
if ((d > FLT_MAX) || (d < -FLT_MAX)) {
return aa_table[ES](lexeme);
}
t.code = FPL_T;
t.attribute.flt_value = (float) d;
Unclear as how OP would like to handle NaN.
[Edit] Now see OP also wants to limit input to 20 char. Suggest:
char buf[20+1];
strncpy(buf, lexeme, 20);
buf[20] = '\0';
volatile double d = atof(buf);
...
The limit tests still make sense as input could be 1.0e100, or beyond FLT_MAX.

How to print the char, integer, float and double values without using format specifiers in c

I want to print the char, int, float and double values without using format specifiers in my c program.
I can able to print the string using the below code:
char s[] = "Hello\n";
fprintf(stdout, s);
how can I print the other data type values?
To print a char, use:
fputc(c, stream)
(If the stream is stdout, you can use putchar(c).)
To print an int:
If the int is negative, print “-”.
Calculate the individual digits of the integer. This can be done either by calculating the digits from least significant to most significant and saving them in a buffer to be printed in reverse order or by figuring out where the most significant digit is and then calculating the digits from most significant to least significant. You can use a remainder operation, such as x % 10, to calculate the least significant digit of a number, and you can use division, such as x / 10, to remove that digit.
One caveat is that, if the original number is negative, you have to be careful about calculating its digits. The % operator will return negative values. Some people attempt to deal with this by negating the integer if it is negative. However, if the number is the least possible int, this may overflow. E.g., in many C implementations, the least int value is -2,147,483,648, but it cannot be negated because the greatest int is 2,147,483,647.
Any digit in numeric form (0 to 10) can be converted to a character (“0” to “9”) by adding '0', such as int d = x % 10; char c = d + '0';. The C standard guarantees that this produces the appropriate character in c.
After you obtain the characters from the digits, print them.
To print a float or double:
Doing this completely correctly is hard, although it is a solved problem. The classic reference for it is Correctly Rounded Binary-Decimal and Decimal-Binary Conversions by David M. Gay.
If you just want a simple implementation suitable for a learning exercise, then you can format a floating-point value much as you would an integer: Calculate the digits individually. You also need to decide whether to print a fixed-point notation or a scientific notation (or other).
To print a fixed-point notation, print the integer part of the value as above, for integer types. Then print a “.” and some digits for the fractional part of the value.
To print a scientific notation, calculate the value of the exponent part (e.g., to express 12345789 as “1.23456789e7”, the exponent is 7, for 107. Divide the value by 10 raised to the power of that exponent and print the resulting value as a fixed-point number (so, in this example, you print “1.23456789”), then print “e”, the print the exponent part.
Floating-point rounding errors will occur in the above, making it suitable only for a learning exercise, not for use in a quality product.
The above should suffice to get you started. It is not complete code, obviously.
just one thought, not very optimal:
int myvalue = 12345;
char buffer[100];
size_t index = 0;
while (myvalue) {
buffer[index] = '0' + myvalue % 10;
myvalue = myvalue / 10;
index++;
}
buffer[index] = '\0';
reverse(buffer);
fprintf(stdout, buffer);
you have to consider the negative sign. And the sizeof buffer (100 is a very bad guess).
To print a char as a character use fputc().
To print an integer (including char) in its decimal form, call either print_unsigned() or print_signed(), depending on if it is a signed integer or an unsigned integer.
The below uses recursion to print the most significant digits first.
For signed integers, it flips positive numbers to negative avoiding the undefined behavior of -INT_MIN.
int print_unsigned(uintmax_t x) {
if (x >= 10) {
if (print_unsigned(x / 10) == EOF) return EOF;
}
return fputc('0' + x % 10, stdout);
}
static int print_signed_helper(intmax_t x) {
if (x <= -10) {
if (print_signed_helper(x / 10) == EOF) return EOF;
}
return fputc('0' - x % 10, stdout);
}
int print_signed(intmax_t x) {
if (x < 0) {
if (fputc('-', stdout) == EOF) return EOF;
} else {
x = -x; // overflow not possible
}
return print_signed_helper(x);
}
The above stops early if the output causes an output error. EOF is something rarely returned from fputc().
To printf a float of double: TBD code.
The short answer is that while it may be possible to hack something together that will do something RESEMBLING what you want (along the lines of Peter Miehle's solution posted in another answer), fundamentally C is not designed for this kind of functionality, and there is no support for it in the language. What you want is function overloading, which C++ and many other higher-level languages provide.
Even Peter Miehle's solution cannot be implemented as a function (in C), because what kind of argument would the function take? Either it is passed a type, in which case we KNOW the type and may as well use printf, or it is passed e.g. a void pointer, in which case, how can it implement the arithmetic operators without knowing the underlying data type the pointer points to?

Convert Int to Hexdecimal without using 'printf' (C Programming)

Is it possible to Convert Int to Hexdecimal without using 'printf'?
Best if the all the value are placed in the variable itself and some sample code with explanation.
The decimal and hexadecimal systems are just ways of expressing the value of the int. In a way "it is already a hexadecimal".
I think you can use itoa in stdlib.h :
char * itoa ( int value, char * str, int base ); or sprintf(str,"%x",value);
The documentation : itoa documentation
Of course it is possible. Just think about how printf itself was originally implemented...
I won't give you a full solution, only hints, based on which you can experiment with the implementation in code:
An 8-bit number can be expressed as 2 hex digits, which contain the higher and lower 4 bits, respectively. To get these bits, you can use the bit-shift (>>) and mask (&) operators.
Once you have a 4-bit value, you can easily map it to the correct hex digit using a sequence of ifs, or (as a more elegant solution) by indexing into a character array.
Hexdecival vs Decimal vs Binary..etc.. are only different bases that represent the same number. printf doesn't convert your number, it generates an hexdecimal string representation of your number. If you want to implement your own study how to make a conversion between decimal and hexdecimal bases.
Yes, it is definitely possible to convert an integer to a hexadecimal string without using the "printf" family of formatting functions.
You can write such a function by converting the number from base-10 (as we think about it) to base-16 (hexadecimal) and printing the digits in that representation (0-9A-F). This will require you to think a lot about the bases we use to represent numbers.
If you are referring to displaying an int as a hexadecimal number in C, than you will have to write a function that does the same thing as printf.
If you are referring to casting or internal representation, it can't be done because hexadecimal is not a data type.
An int is stored in your computer as a binary number. In fact, since hex can be interpreted as a shorthand for writing binary, you might even say that when you print out a decimal number using printf, it has to be converted from hex to decimal.
it's an example for convert a char array to hex string format
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
unsigned char d=255;
char hex_array[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char *array_to_hex_string(uint8_t data[],int size);
char test_data[3] = {'0',188,255};
int main()
{
printf("%s",array_to_hex_string(test_data,3));
return 0;
}
char *array_to_hex_string(uint8_t data[],int size){
int i,j;
char *hex_string = (char *)malloc((2*size) * sizeof(data[0]));
for(i=0;i<size;i++){
hex_string[j] = hex_array[(data[i]>>4)];
hex_string[j+1] = hex_array[(data[i] & 15)];
j +=2;
}
return (char *)hex_string;
}
cout << hex << intvar << endl;
But if you want an answer that gives you an A for your homework, you're not going to get lucky :)

Resources