Float Calculation in Cooja - c

I'm using RPL in Contiki 3.0 and I need to make some calculations where the results are float. But instead of giving me the result in float, it is only calculating the integer number for example:
5/2 = 2.0 instead of 2.5. How can I get the right answer?
I can not print float or double in Contiki 3.0 so I'm using this code to convert float into a string:
// Reverses a string 'str' of length 'len'
void reverse(char* str, int len)
{
int i = 0, j = len - 1, temp;
while (i < j) {
temp = str[i];
str[i] = str[j];
str[j] = temp;
i++;
j--;
}
}
// Converts a given integer x to string str[].
// d is the number of digits required in the output.
// If d is more than the number of digits in x,
// then 0s are added at the beginning.
int intToStr(int x, char str[], int d)
{
int i = 0;
while (x) {
str[i++] = (x % 10) + '0';
x = x / 10;
}
// If number of digits required is more, then
// add 0s at the beginning
while (i < d)
str[i++] = '0';
reverse(str, i);
str[i] = '\0';
return i;
}
// Converts a floating-point/double number to a string.
void ftoa(float n, char* res, int afterpoint)
{
// Extract integer part
int ipart = (int)n;
// Extract floating part
float fpart = n - (float)ipart;
// convert integer part to string
int i = intToStr(ipart, res, 0);
// check for display option after point
if (afterpoint != 0) {
res[i] = '.'; // add dot
// Get the value of fraction part upto given no.
// of points after dot. The third parameter
// is needed to handle cases like 233.007
fpart = fpart * powf(10, afterpoint);
intToStr((int)fpart, res + i + 1, afterpoint);
}
}
I appreciate your help
Thanks
Hanin

If you want to print a number as a float, simply print the part before the floating point as an integer, print the dot, and then multiply the part after the floating point with a power of 10 and print it as another integer. For example, if you want to print 6 digits after the floating point, multiply the fractional part with 1000000.
You will need a separate buffer to print the part after the floating point first - the first digit must be nonzero, so the safe option to pad the number with another digit e.g. "1" that you do not print. To do that, simply add the 1.0 to the fractional part before multiplying it.
Here is the complete code:
float f = 5.0 / 2;
char fractional_part[10];
sprintf(fractional_part, "%d", (int)((f - (int)f + 1.0) * 1000000));
printf("%d.%s\n", (int)f, &fractional_part[1]); // prints "2.500000"

Because 5/2 is a form of integer division, what you put in you get out, meaning that if you put in 5/2 you will only get an integer back, in the form of 2.
To fix this, make your 5/2 is 5/2.0 so that it is read in as a float, and that will make sure that you will get an answer that is a floating-point decimal.

I also wanted to print float value in cooja, so I found this solution.
// digits before point
unsigned short d1(float f){
return((unsigned short)f);
}
// digits after point
unsigned short d2(float f){
return(1000*(f-d1(f)));
}
int main()
{
float max = 6.796;
printf("max value %u.%u \n", d1(max) , d2(max));
}

Related

Decompose decimal part of a double

I need to decompose a decimal part of a number in single digits, but I need to get the most obvious representation. Here is my code, to be clearer :
#include <stdio.h>
void main(){
double value = 0.123;
int decim_tab[6];
int decimal;
int i;
for (i = 0; i < 6; ++i) {
value *= 10;
decimal = (int)value;
decim_tab[i] = decimal;
value -= decimal;
}
for (i = 0; i < 6; ++i)
print("%d\n", decim_tab[i]);
}
The output I need is :
1
2
3
0
0
0
But I get :
1
2
2
9
9
9
EDIT
A solution I found is to add a small delta to the value in order to force the shortest representation :
#include <stdio.h>
void main(){
double value = 0.123;
int decim_tab[6];
int decimal;
int i;
value += 0.000000001
for (i = 0; i < 6; ++i) {
value *= 10;
decimal = (int)value;
decim_tab[i] = decimal;
value -= decimal;
}
for (i = 0; i < 6; ++i)
print("%d\n", decim_tab[i]);
}
I would be happy to find a better way, any suggestions ?
The reason you get unexpected output is that decimal fractions cannot always be exactly represented using (most common) base two floating point numbers. Using printf("%.20f", value); after your assignment of value you will see that the value 0.123 is actually being stored as 0.12299..., which is why you receive that output.
If you only need to print out six digits, you can use string formatting of floating point numbers:
#include <stdio.h>
#include <stdlib.h>
int main(){
double value = 0.123;
char *s = malloc(9);
sprintf(s++, "%.6f", value);
while(*s++){
putchar(*s);
putchar('\n');
}
}
EDIT: The code in my answer is very specific to the example you gave, so when using it be aware that I made some assumptions, e.g. your value will never have more than one digit before the decimal point.
If you want 6 decimal places, you should add 0.0000005 (ie 0.5e-6) to round the value to the nearest place. This method will work for positive numbers, first extract the sign, then work on the absolute value.
Floating point numbers are not exact value representation. Here's a simple sample:
double a = 0.15 + 0.15; // 0.15 + 0.15 == 0.3, right?
double b = 0.1 + 0.2; // 0.1 + 0.2 == 0.3, right?
if (a == b) {
printf("Equal\n");
} else {
printf("Unequal\n");
}
What will that print? Equal? Are you sure? Try it yourself:
http://rextester.com/VZOZ1043
It prints Unequal, that's because there are some numbers that floating point can't represent exactly and that's something you always need to keep in mind when doing floating point math. Also there is rounding involved in many operations, so the results of math operations are as good as possible but not always "exact", there's a tiny error that can also sum up if you run multiple operations.
double value = 0.123;
// Assuming none of your numbers has more than 58 digits,
// one period and one termination char.
char buffer[60];
// Print the number to the buffer.
// Missing: Error checking if it did fit!
snprintf(buffer, sizeof(buffer), "%f", value);
// Find the period or end of string
int idx = 0;
for (; buffer[idx] && buffer[idx] != '.'; idx++);
// Print anything after the period till
// the end of the string
if (buffer[idx] == '.') {
for (idx++; buffer[idx]; idx++) {
printf("%c\n", buffer[idx]);
}
}
Test it: http://rextester.com/CYDQO24769

How to sum digits before and after decimal point separately in C?

I'm supposed to get a decimal number and sum the whole part digits separately and the decimal part separately,
so for example if I get:
1321.0365
the output should be: 7.14
I'm supposed to do that without using arrays.
this is what I tried to do by far, after getting the number from a function, first separating both parts, then multiplying the decimal number by 10, until the number is equal to the int part.
then I tried to sum each of the parts separately, and after i do that, divide the decimal part until the number is equal to the int number.
theoretically it sounds like it should work, but I think I miss something on the way.
this is what I've done so far:
double number;
double sumReal=0;
int wholePart;
int sumWhole=0;
int multiply=1;
number=getDecimalNumber();
wholePart=number;
number-=wholePart;
while(number!=(int)number)
number*=10;
while (number!=0)
{
sumReal+=(int)number%10;
number/=10;
}
while (wholePart!=0)
{
sumWhole+=(int)wholePart%10;
wholePart/=10;
}
while(sumReal!=(int)sumReal)
sumReal/10;
number=wholePart+sumReal;
somehow most of the parts seem to work, but multiplying the real part by 10 always gets me 0, and when summing the real part and the whole number at the end also gets me 0, which leads me to a 0 output.
#include <stdio.h>
int main(){
int ch;
int n1 = 0, n2 = 0;
while((ch=getchar())!= '.'){
n1 += ch - '0';
}
while((ch=getchar())!= '\n'){
n2 += ch - '0';
}
printf("%d.%d\n", n1, n2);
return 0;
}
It's easier to go this way :
use the number as string (get a char* pointer on the string so you don't actively use an array)
split on the decimal point separator
(you get two char* pointers, one per string)
iterate on one string char by char (increment the pointer), convert the current char in int and add
same with second string
you're done
I strongly suspect it is what your teacher want you to do, more than exotic calculations.
here is one way to write the algorithm
It may still have bugs that will need the OPs attention
#include <math.h>
// prototypes
double getDoubleNumber(void);
double sumOfDigits( void );
double sumOfDigits()
{
double doubleNumber = 0.0;
double wholePart;
double fractionPart;
int sumWhole=0;
int sumFraction = 0;
double sumParts=0.0;
// get the original number
doubleNumber=getDoubleNumber();
wholePart = trunc(doubleNumber);
// calc fractional part
fractionPart = doubleNumber - wholePart;
// this may need modification due to inexact representation of value
// move fractionPart to left of decimal point
while(fractionPart > floor(fractionPart) )
{
fractionPart *= 10.0;
}
while( trunc(fractionPart) )
{
sumFraction += trunc( fmod( fractionPart, 10.0);
fractionPart /= 10.0;
}
// move fractionPart back to right of decimal point
while( trunc(sumFraction) )
{
sumFraction /= 10.0;
}
// calc sum of whole part digits
while ( trunc(wholePart) )
{
sumWhole += trunc( fmod( wholePart, 10.0 ) );
wholePart /= 10.0;
}
sumParts = sumWhole+sumFraction;
return( sumParts );
} // end function: sumOfDigits

Convert a hexadecimal to a float and viceversa in C

I'm trying to write an algorithm to convert a hexadecimal number to a floating point number and vice versa. This is part of an assignment, the program is supposed to receive either an 8 digit hexadecimal number that starts with '0x' or a floating point number, and using the computer's 'built in IEEE 754 capabilities' convert the number to hex or float. The code should be in C.
My approach is the following. Store the input by the user as a string. Pass the input char array to a method that checks if it's a hexadecimal number by checking the first two positions of the array, which should be 0 and X (assume all hex numbers are passed this way). If this is the case, then I check that the hex is in the appropriate form, i.e not too many digits or numbers outside the 0-15 range (also considering the ABCDEF convention).
So, my problem is, I don't know how to turn this array back into a number that I can use to convert to floating point. I thought about using sscanf to turn it back into a float but I don't know enough C and haven't found any good sources online
Can somebody point me in the right direction? I also thought about storing the user input both as a string and a number at the same time, but I am not sure if this is possible.
Here are the two form checking functions and the incomplete main method:
int is_hex(char arr[])
{
if (arr[0] == '0' && (arr[1] == 'x' || arr[1] == 'X')) {
return 1;
}
return 0;
}
int check_if_good(char arr[])
{
if (is_hex(arr)) {
int len = strlen(arr);
for (int i = 2; i < len; i++) {
if ((arr[i] > 'f' && arr[i] <= 'z') || (arr[i] > 'F' && arr[i] <= 'Z')) {
return 0;
}
}
}
return 1;
}
int main(int argc, const char * argv[])
{
float x;
char input[30];
scanf("%s", input);
printf("%s", input);
return 0;
}
If somebody could also tell me the basics of what '%x' means i would really appreciate it. From what I understand it lets me collect numbers in hexadecimal form, but can i store them in ints and floats? Thank you very much for your help.
--Edit: Extra code for floris. I'm trying to solve this problem without using any extra libraries, so you can't use the stdint lib.
char input[30];
scanf("%s", input);
if(check_if_good(input)){ //Ignore this if-statement.
printf("Input is in hex form");
}
int num = convert_hex_string(input); // this function works perfectly. It return the int form of the hex.
double f = *((double*)&num);
printf("%f\n", f);
If you actually want to know what floating point number is represented by a particular hex string, you can convert the string to an integer, then look at the address pretending that it contains a floating point number. Here's how that would work:
#include <stdint.h>
#include <stdio.h>
int main(void) {
char myString[]="0x3f9d70a4";
uint32_t num;
float f;
sscanf(myString, "%x", &num); // assuming you checked input
f = *((float*)&num);
printf("the hexadecimal 0x%08x becomes %.3f as a float\n", num, f);
}
This produces as output
the hexadecimal 0x3f9d70a4 becomes 1.230 as a float
As expected. See my answer to your other question about a related topic for more details.
It should also be easy to see how you can do the above in reverse - start with a floating point number, and get the hexadecimal representation.
If you are permitted to use library functions, try atoi(arr) or sscanf(arr+2, "%x", &num)
If you want to parse the string manually, think about how you'd convert a decimal number. For example, converting "2987" to an integer...
int n = 0;
n += 1000 * 2;
n += 100 * 9;
n += 10 * 8;
n += 1 * 7;
Now apply the technique to hexadecimal. Here is a code snippet to do a single ascii character:
int char_to_int(char c) {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
return 0; /* oops, something else... */
}
You'll need to use either multiplication or bit operations. After you do your bounds/hex checking you described, do something like this:
float x = 0;
for(i=0;i<8;i++)
{
x += getDecimalValue(inputArray[i+2]) << (4*(7-i))
}
This is untested code & you will need to do the conversion from char to decimal value (A=10, B=11 ect). That bitwise operation is the same as multiplying the decimal equivalent of the hex character by 2^numberOfBits. This answer is assuming the leftmost hex is the most significant (Big endian), reverse the operation for little endianess.
If the input is in the form: "0x......" then
float f;
long l;
l = strtol(input, (char**)NULL, 16);
f = (float)l;
printf("%f", f);
valter

High-precision program that calculates 2^n

I'm building a program in C that can get powers of 2. The user inputs the value of n, and the program calculates 2^n.
Here's the code.
The problem comes when I input 100
What I am getting:
1,267,650,600,228,229,400,000,000,000,000
What I should get
1,267,650,600,228,229,401,496,703,205,376
It has to be coded entirely in ANSI C. Any ideas on how to increase the precision? The maximum value of N has to be 256 (256 bits, I imagine, which means the maximum output should be 2^256).
What I'm lacking here is precision, and I don't know how to fix that. Any ideas?
I think it's easiest if you work in base 10 from the start. This is because while calculating powers of 2 in binary is trivial, the conversion back to base 10 is a lot harder.
If you have an array of base 10 digits1, you only need to implement base 10 addition with carry to be able to multiply by 2 (by adding the number to itself). Do that n times in a loop and you have your answer.
If you wish to support higher exponents, you can also look into implementing exponentiation by squaring, but that's harder, since you'll need general multiplication, not just by 2 for that.
1 Tip: It's more convenient if you store the digits in reverse order.
Here is my quick and dirty implementation of hammar's approach., storing the decimal number as a C string with the digits in reverse order.
Run the code on ideone
void doubleDecimal(char * decimal)
{
char buffer[256] = "";
char c;
unsigned char d, carry = 0;
int i = 0;
while (c = decimal[i])
{
d = 2 * (c - '0') + carry;
buffer[i] = (d % 10) + '0';
carry = d / 10;
i++;
}
if (carry > 0)
buffer[i++] = (carry % 10) + '0';
buffer[i] = '\0';
strncpy(decimal, buffer, 256);
}
void reverse(char * str)
{
int i = 0;
int j = strlen(str) - 1;
while (j > i)
{
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
i++;
j--;
}
}
int main(void)
{
char decimal[256] = "1";
int i;
for (i = 0; i < 100; i++)
doubleDecimal(decimal);
reverse(decimal);
printf("%s", decimal);
return 0;
}
Output:
1267650600228229401496703205376
double is a (probably) 64bit value. You can't store 256 bits of precision in 64 bits. The reason that you are getting a number that is sort of close is because floating point numbers are stored with varying precision -- not all sequential numbers can be represented, but you can represent very large numbers. Pretty useless in this case.
What you want is either to use an arbitrary precision library or, since this is probably homework, you are expected to write your own.
A typical double, using 64-bit IEEE 754, has about 51 bits precision, IIRC.
Most probably the point of supporting exponents up to 256 is to exceed that precision, and also the precision of a long double or long long, so that you have to do things yourself.
As a homework exercise, then,
Store decimal digit values in an array + a digit count
Implement doubling of the value in such array + count
Start with 1 and double value appropriate number of times.
A few things you'll want to think about to solve this:
You are only dealing with integers so you should use an integer
representation (you will need to roll your own because you can't use
long long which is "only" 64 bits long).
Powers of 2 you say -how convenient - computers store numbers using powers of 2 (you'll
only need to use shift operations and bit fiddling .... no
multiplications will be needed).
How can you convert a base 2 number to a base 10 number for display purposes (think of division and outputting one number at a time (think about what a hardware divisor does in order to get the bit manipulations correct).
You can't the store 256 bits of precision in 64 bits. Reason that you are getting a number to close is because floating point numbers are stored with varying precision. To all sequential numbers can be represented, but you can represent very large numbers. Pretty useless in this case.
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//constants
#define MAX_DIGITS 1000
//big integer number struct
struct bigint {
char Digits[MAX_DIGITS];
};
//assign a value
void assign(struct bigint* Number,int Value) {
if (Value!=1) {
printf("Can not assign value other than 1\n");
exit(0);
}
memset(Number,0,sizeof(bigint));
Number->Digits[0] = Value;
}
//multiply the big integer number with value
void multiply(struct bigint* Number,int Value) {
int Digit,New_Digit;
int Carry = 0;
for (int Index=0; Index<MAX_DIGITS; Index++) {
Digit = Number->Digits[Index];
New_Digit = Digit*Value%10;
if (New_Digit+Carry<10) {
New_Digit = New_Digit+Carry;
Carry = Digit*Value/10;
}
else {
New_Digit = (New_Digit+Carry)%10;
Carry = (Digit*Value/10)+1;
}
//set the new digit
Number->Digits[Index] = New_Digit;
}//for loop
}
//print out the value of big integer type
void print(struct bigint* Number) {
int Index = MAX_DIGITS-1;
while (Number->Digits[Index]==0 && Index>=0)
Index--;
//the big integer value is zero
if (Index==-1) {
printf("0");
return;
}
while (Index>=0) {
printf("%u",Number->Digits[Index]);
Index--;
}
}
//main programme entry point
int main(int Argc,char** Args) {
int Power = 100;
struct bigint Number;
//assign the initial value
assign(&Number,1);
//do the multiplication
for (int Index=0; Index<Power; Index++)
multiply(&Number,2);
//print result
print(&Number);
getch();
}
//END-OF-FILE

Splitting a double into an array in C

I'd like the following code to work:
double num = 31415; /* num will never have a decimal part */
/* ... code here so that we can now say */
printf("%d", num_array[0] == 3 && num_array[1] == 1 && num_array[4] == 5); //1
I realize it's trivial to do this with ints (just int i=0; while(num>0) numarr[size-++i] = num%10, num/=10; where size is predetermined to be the number of digits in the number), but that obviously won't work for floats/doubles because you can't mod one floats.
And yes, I need to use floats/doubles, despite not using the floating point section (it's an exercise).
And I have figured out how to determine the number of digits in a double, using floor().
/* n > 0, n=floor(n) */
int numdigits(double n){
int i = 0;
while (n >0)
n = floor(n/10), i++;
return i;
}
Look up fmod. The number of digits will probably be easier to compute using log10.
It's probably easiest to just convert it to a string:
char* str = malloc(num_digits+1);
snprintf(str, num_digits+1, "%f", num);
Indexing into str will give you each digit as an ASCII value, so you'll need to subtract '0' to get the actual numeric value:
str[0] - '0' == 3;
str[1] - '0' == 1;
str[2] - '0' == 4;
...
Apart from fmod(), you could also cast to a int64_t or long long int, and use % as before. If the range is less than 10 digits, you could use a int32_t.

Resources