Concatenating longs and floats into a long - c

I have two numbers:
1234567890 <--- Long
and
0.123456 <--- Float
Is there any way to combine these to make a float(or double) in the following format:
(123)4567890.123456
I don't mind if the numbers in brackets have to be removed.

Given a long l and a float f, you can use:
double result = l % 10000000 + (double) f;
This will usually lose some accuracy in the fraction portion.
Update: From a comment, we learn that these values are a time represented as a number of seconds and a fraction of a second and that it is desired to calculate an interval. If we want to find the difference between two times, then we can calculate the difference with fewer problems from accuracy and precision this way:
double SubtractTimes(long l0, float f0, long l1, float f1)
{
long ld = l1 - l0;
double fd = (double) f1 - f0;
return ld + fd;
}
Note: If there is a concern that the time may have wrapped around some upper limit, then the code should test for this and make adjustments.

I must be missing something. Isn't it as easy as this?
long l = 1234567890;
float f = 0.123456;
float result = l + f;

Use this:
double result = l + f;
printf("%.6f",result);

Related

Am I dividing in the right way in C?

I need to apply a formula to three variables. Some of the operations (divisions) give me a 0 instead of the proper number. So I get a different result from what I expected from the formula.
I think that the problem is related to the way C manages data types and their remainders. For this reason, I tried to transform int variables into float variables or to round the numbers that I divided. But all of this is still not working and I'm not able to understand what I'm missing.
Could you please have a look at my code and let me know where is the mistake?
Thanks
double grade(int lc, int wc, int sc)
{
wc = (float)wc;
lc = (float)lc;
sc = (float)sc;
float L = round((wc/100)/lc);
float S = round((wc/100)/sc);
float index = 0.0588 * L - 0.296 * S - 15.8;
return index;
}
Problem:
wc = (float)wc;
lc = (float)lc;
sc = (float)sc;
All these statements do not do what you think because the types of these variables are originally int.
You are converting an int to float and assigning it back to int.
Solution:
Pass the values to a float rather than int to the function, implicit conversion will take care of the rest.
Change your function signature to
double grade(float lc, float wc, float sc)
Or just do this (the other operands will not need the cast to float since it enough if only one of the operands is it, then the others will be converted to it implicitly)
double grade(int lc, int wc, int sc)
{
float L = round(((float)wc/100)/lc);
float S = round(((float)wc/100)/sc);
float index = 0.0588 * L - 0.296 * S - 15.8;
return index;
}
Note that the return type is double, but you use just floats. Use double instead of floats in the function as types as well OR change return type to float.
The mistake is that this wc = (float)wc; is essentially this wc = (int)(float)wc; since wc type is int. Basically nothing happens, therefore when you make your calculation like wc/100, then this will be an integer division resulting in integer, so if wc is less than 100 (and >= 0), then the result is 0 and not a real number as you would expect.
wc = (float)wc; casts an int to a float, converts back to int, then assigns. No real benefit here.
wc/100 is integer division, which discards the fraction of the quotient. Not likely what OP wants.
Converting int to float risks losing precision as so a less precise answer. double is better for wide ranging int values.
Code mixes uses of float and double with a call to a double round(double), double multiplication and conversions from float to double to float to double. Simplify and use double throughout.
double grade(int lc, int wc, int sc) {
// v------v `double` division
double L = round(wc/100.0/lc);
double S = round(wc/100.0/sc);
return 0.0588 * L - 0.296 * S - 15.8;
}

Trouble when computing modulos with floats in C

I am not an expert in programming, and I am facing the following issue.
I need to compute modulo between floats A and B.
So I use fmod((double)A, (double)B).
Theorically, if A is a multiple of B, then the result is 0.0.
However, due to floating point precision purpose, A and B are not exactly the number I expected to have.
Then, the result of the modulo computation is not 0.0, but something different.
Which is problematic.
Example:
A=99999.9, but the compiler interprets it as 99999.898.
B=99.9, but the compiler interprets it as 99.900002.
fmod(A,B) expected to be 0.0, but gives actually 99.9.
So the question is: how do you use to manage this kind of situation ?
Thank you
The trouble is that:
A is not 99999.9, but 99999.8984375 and
B is not 99.9, but 99.90000152587890625 and
A mod B is 99.89691162109375
OP is getting the correct answer for the arguments given.
Need to use different augments.
A reasonable alternative is to convert the arguments by a scaled power-of-10, then round to an integer, %, back to floating point and un-scale.
Overflow is a concern.
Since OP wants to treat numbers to the nearest 0.1, scale by 10.
#include <float.h>
#include <stdio.h>
int main(void) {
float A = 99999.9;
float B = 99.9;
printf("%.25f\n", A);
printf("%.25f\n", B);
printf("%.25f\n", fmod(A,B));
long long a = lround(A*10.0);
long long b = lround(B*10.0);
long long m = a%b;
double D = m/10.0;
printf("D = %.25f\n", D);
return 0;
}
Output
99999.8984375000000000000000000
99.9000015258789062500000000
99.8969116210937500000000000
D = 0.0000000000000000000000000
Alternative
long long a = lround(A*10.0);
long long b = lround(B*10.0);
long long m = a%b;
double D = m/10.0;
Scale, but skip the integer conversion part
double a = round(A*10.0);
double b = round(B*10.0);
double m = fmod(a,b);
double D = m/10.0;

precision between float and double in C

I understand there are several topics same as mine, but I still don't really get it, so I'm expecting someone could explain this in a more simple but explicit way for me instead of pasting other topics' links, thanks.
Here's a sample code:
int a = 960;
int b = 16;
float c = a*0.001;
float d = a*0.001 + b;
double e = a*0.001 + b;
printf("%f\n%f\n%lf", c, d, e);
which outputs:
0.960000
16.959999
16.960000
My two questions are:
Why does adding an integer to a float ends up as the second output, but changing float to double solves the problem as the third output?
Why does the third output have the same number of digits with the first and second output after the decimal point since it should be a more precise value?
The reason why they produce the same number of decimal places, is because 6 is the default value. You can change that as in the edited example below, where the syntax is %.*f. The * can be either a number as shown below, or in the second case, supplied as another argument.
#include <stdio.h>
int main(void) {
int a = 960;
int b = 16;
float c = a*0.001;
float d = a*0.001 + b;
double e = a*0.001 + b;
printf("%.9f\n", c);
printf("%.*f\n", 9, d);
printf("%.16f\n", e);
}
Program output:
0.959999979
16.959999084
16.9600000000000009
The extra decimal places now shows that none of the results is exact. One reason is because 0.001 cannot be exactly coded as a floating point value. There are other reasons too, which have been extensively covered.
One easy way to understand why, is that a float has about 2^32 different values that can be encoded, however there is an infinity of real numbers within the range of float, and only about 2^32 of them can be represented exactly. In the case of the fraction 1/1000, in binary it is a recurring value (as is the fraction 1/3 in decimal).
I think the calculation a*0.001 will be done in double precision in both cases, then some precision is lost when you store it as a float.
You can choose how many decimal digits are printed by printf by writing e.g. "%.10lf" (to get 10 digits) instead of just "%lf".

Fast rounding float on three digits precision in C

I have seen this code:
(int)(num < 0 ? (num - 0.5) : (num + 0.5))
(How to round floating point numbers to the nearest integer in C?)
for rounding but I need to use float and precision for three digits after the point.
Examples:
254.450 should be rounded up to 255.
254.432 should be rounded down to 254
254.448 should be rounded down to 254
and so on.
Notice: This is what I mean by "3 digits" the bold digits after the dot.
I believe it should be faster then roundf() because I use many hundreds of thousands rounds when I need to calculate the rounds. Do you have some tips how to do that? I tried to search source of roundf but nothing found.
Note: I need it for RGB2HSV conversion function so I think 3 digits should be enough. I use positive numbers.
"it should be faster then roundf()" is only verifiable with profiling various approaches.
To round to 0 places (round to nearest whole number), use roundf()
float f;
float f_rounded3 = roundf(f);
To round to 3 places using float, use round()
The round functions round their argument to the nearest integer value in floating-point format, rounding halfway cases away from zero, regardless of the current rounding direction.
#include <math.h>
float f;
float f_rounded3 = round(f * 1000.0)/1000.0;
Code purposely uses the intermediate type of double, else code code use with reduced range:
float f_rounded3 = roundf(f * 1000.0f)/1000.0f;
If code is having trouble rounding 254.450 to 255.0 using roundf() or various tests, it is likely because the value is not 254.450, but a float close to it like 254.4499969 which rounds to 254. Typical FP using a binary format and 254.450 is not exactly representable.
You can use double transformation float -> string -> float, while first transformation make 3 digits after point:
sprintf(tmpStr, "%.3f", num);
this work for me
#include <stdio.h>
int main(int ac, char**av)
{
float val = 254.449f;
float val2 = 254.450f;
int res = (int)(val < 0 ? (val - 0.55f) : (val + 0.55f));
int res2 = (int)(val2 < 0 ? (val2 - 0.55f) : (val2 + 0.55f));
printf("%f %d %d\n", val, res, res2);
return 0;
}
output : 254.449005 254 255
to increase the precision just add any 5 you want in 0.55f like 0.555f, 0.5555f, etc
I wanted something like this:
float num = 254.454300;
float precision=10;
float p = 10*precision;
num = (int)(num * p + 0.5) / p ;
But the result will be inaccurate (with error) - my x86 machine gives me this result: 254.449997
When you can change de border from b=0.5 to b=0.45 you must know that for positives the rounded value is round_0(x,b)=(int)( x+(1-b) ) therefore b=0.45 ⟹ round_0(x)=(int)(x+0.55) and you can threat the signal. But remember that don't exists 254.45 but 254.449997 and 254.449999999999989, maybe you prefer to use b=0.4495.
If you have float round_0(float) to zero-digit rounding (can be like you show in question), you can do for one, two... n-digit rounding like this in C/C++: # define round_n(x,n) (round_0((x)*1e##n)/1e##n).
round_1( x , b ) = round_0( 10*x ,b)/10
round_2( x , b ) = round_0( 100*x ,b)/100
round_3( x , b ) = round_0( 1000*x ,b)/1000
round_n( x , b , n ) = round_0( (10^n)*x ,b)/(10^n)
But do typecast to int and (one more typecast) to float to operate is slower than rounds in operations. If don't simplify the add/sub (some compilers have this setting) for faster zero-digit round to float type you can do it.
inline float round_0( float x , float b=0.5f ){
return (( x+(0.5f-b) )+(3<<22))-(3<<22) ; // or (( x+(0.5f-b) )-(3<<22))+(3<<22) ;
}
inline double round_0( double x , double b=0.5 ){
return (( x+(0.5-b) )+(3<<51))-(3<<51) ; // or (( x+(0.5-b) )-(3<<51))+(3<<51) ;
}
When b=0.5 it correctly rounds to nearest integer if |x|<=2^23 (float) or |x|<=2^52 (double). But if compiler uses FPU (ten bytes floating-point) optimizing loads then constant is 3.0*(1u<<63), works |x|<=2^64 and use long double can be faster.

Floating point in C

I am asking a user for two non-negative integer values in C. I then want to convert these to percentages (expressed as decimals). Unfortunately, my floats are coming up as zeroes. Why is this, and how do I fix it?
int a = 5;
int b = 10;
int total = a + b;
float a_percent = a / total;
float b_percent = b / total;
printf("%.2f, %.2f\n", a_percent, b_percent);
You aren't using floats, you're using integers, and so the integral division gives zero (which is then assigned to a float).
To perform a floating-point operation, you must first convert the integers (or at least one of them) to a float. Conveniently, we just use total:
float total = a + b; // exact
float ap = a / total;
float bp = b / total; // OK, these are now floating-point operations
In addition to the problems others have pointed out, the ratio won't be a percentage until you multiply it by 100.0.
An int divided by an int will always return an int. You'll have to make one of the two arguments a float before dividing:
float a_percent = (float) a / total;
float b_percent = (float) b / total;
I am not a C expert, but my guess is because dividing an int by an int always results in an int.
You may need to do something like this:
float a_percent = (float)a/total;
float b_percent = (float)b/total;
You're first performing an integer division, then converting the result to floating point. This will not give the results you want. Either make total a floating point value to begin with (so that the types get automatically promoted right) or cast a and b to (float) before performing the division.
You are using integer math not floating point here.
Try:
float a_percent = a/(float)total;
float b_percent = b/(float)total;
For a simple percentage you may be happier using fixed-point. Just multiply your numerator (a or b) by 100 and you'll get the percentage from the division. forex:
int a = 5;
int b = 10;
int total = a + b;
int a_percent = 100*a/total;
int b_percent = 100*b/total;
printf("a%%=%d, b%%=d\n", a_percent, b_percent);

Resources