Function to scale float values to (0-100) in C - c

I am trying to convert a float variable into an integer of value between 0 and 100. The float is always positive. the corresponding integer value should reflect the size of the float value compared to the maximum value for a 32-bit float, e.g. 0.0 converts to 0 and 3.402823466 E + 38 converts to a 100, and anything else goes in between.
Here is what I have so far but I keep getting -1 as the output for any non-zero input.
int convFloat(float x){
int y;
y = (int) (x/3.4e38) * 100;
return y;
}
What am I doing wrong here?

This:
y = (int) (x/3.4e38) * 100;
// ^--------------^
// cast (x/3.4e38)to int
Should be:
y = (int) ((x/3.4e38) * 100);
// ^----------------------^
// cast ((x/3.4e38) * 100)to int

((union { float f; uint32_t u; }){ val }.u>>23&255)*100/255

Related

Compare 2 floats by their bitwise representation in C

I had this question on my exam, and I couldn't realy solve it, will appreciate some help.
Fill the blanks only, function must return true if and only if x<y.
Assume x,y cannot be NaN (but can be +-inf) no casting is allowed, use only ux, uy, sx, sy
bool func(float x, float y) {
unsigned* uxp = ______________ ;
unsigned* uyp = ______________ ;
unsigned ux = *uxp;
unsigned uy = *uyp;
unsigned sx = (ux>>31);
unsigned sy = (uy>>31);
return ___________________________;
}
Presumably the assignment assumes float uses IEEE-754 binary32 and unsigned is 32 bits.
It is not proper to alias float objects with an unsigned type, although some C implementations support it. Instead, you can create a compound literal union, initialize its float member with the float value, and access its unsigned member. (This is supported by the C standard but not by C++.)
After that, it is simply a matter of dividing the comparison into cases depending on the sign bits:
#include <stdbool.h>
bool func(float x, float y) {
unsigned* uxp = & (union { float f; unsigned u; }) {x} .u;
unsigned* uyp = & (union { float f; unsigned u; }) {y} .u;
unsigned ux = *uxp;
unsigned uy = *uyp;
unsigned sx = (ux>>31);
unsigned sy = (uy>>31);
return
sx && sy ? uy < ux : // Negative values are in "reverse" order.
sx && !sy ? (uy | ux) & 0x7fffffffu : // Negative x is always less than positive y except for x = -0 and y = +0.
!sx && sy ? 0 : // Positive x is never less than negative y.
ux < uy ; // Positive values are in "normal" order.
}
#include <stdio.h>
int main(void)
{
// Print expected values and function values for comparison.
printf("1, %d\n", func(+3, +4));
printf("1, %d\n", func(-3, +4));
printf("0, %d\n", func(+3, -4));
printf("0, %d\n", func(-3, -4));
printf("0, %d\n", func(+4, +3));
printf("1, %d\n", func(-4, +3));
printf("0, %d\n", func(+4, -3));
printf("1, %d\n", func(-4, -3));
}
Sample output:
1, 1
1, 1
0, 0
0, 0
0, 0
1, 1
0, 0
1, 1

How to keep checking if a calculated number is an integer or not?

I would like to keep calculating d until it's an integer, if it is not an integer then increment a number by 1, if it is then return the integer. I have tried this but I keep getting the float number returned as an integer. (e.g. 19.4 will be returned as 19 but i just want to keep calculating it until i get an integer). I have tried the following code:
int calcD(int tn, int e){
int z;
float d;
z = 1;
while (true){
d = (1+(z*tn))/e;
if (fmodf(d, 1)!= 0){
z++;
}else{
break;
}
}
return d;
}
Thank you for any help!
Your question is how to tell if the result of division is an integer. That means checking if the numerator is a multiple of the denominator. That's pretty simple -- find the closest multiplier, multiply the denominator by it, and see if you get the numerator.
So:
while (true){
num = 1 + (z * tn);
d = num / e;
if (d * e != num)
z++;
}else{
break;
}
Just compare the value against the value you get when you round it.
float f = ...
float precision = 0.00001;
if (fabsf(f - roundf(f)) < precision) {
printf("integer\n");
} else {
printf("not integer\n");
}

casting signed to double different result than casting to float then double

So as part of an assignment I am working if a expression : (double) (float) x == (double) x
returns awlays 1 or not.(x is a signed integer)
it works for every value except for INT_MAX. I was wondering why is it so? if i print the values, they both show the same value,even for INT_MAX.
x = INT_MAX ;
printf("Signed X: %d\n",x);
float fx1 = (float)x;
double dx1 = (double)x;
double dfx = (double)(float)x;
printf("(double) x: %g\n",dx1);
printf("(float) x: %f \n",fx1);
printf("(double)(float)x: %g\n",dfx);
if((double) (float) x == (double) x){
printf("RESULT:%d\n", ((double)(float) x == (double) x));
}
EDIT: the entire program:
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
int main(int argc, char *argv[]){
//create random values
int x = INT_MAX ;
printf("Signed X: %d\n",x);
float fx1 = (float)x;
double dx1 = (double)x;
double dfx = (double)(float)x;
printf("(double) x: %g\n",dx1);
printf("(float) x: %f \n",fx1);
printf("(double)(float)x: %g\n",dfx);
if((double) (float) x == (double) x){
printf("RESULT:%d\n", ((double)(float) x == (double) x));
}
return 0;
}//end of main function
int and float have most likely the same number of bits in their representation, namely 32. float has a mantissa, an exponent and a sign bit, so the mantissa must have less than 31 bit, needed for the bigger int values like INT_MAX. So there loss of precision when storing in float.

Round up a float number that has a non-zero decimal digit

I was asking about round a number half up earlier today and got great help from #alk. In that post, my thinking was to round up 4.5 to 5 but round 4.4 down to 4. And the solution given by #alk was:
int round_number(float x)
{
return x + 0.5;
}
and it works very elegantly!
In this post, I would like to discuss how to implement the ceil() function in C.
Along the same line as the last solution given by #alk, I came up with the following:
int round_up(float y)
{
return y + 0.99999999;
}
This works for all situations except when the the float number y has .00000001. I am wondering if there's any better way to do the same thing as ceil() in C.
Unless you reliably know the epsilon of float (I'm not sure standard C provides that), I think you're stuck with return (y < 0 || y == (int)y) ? y : y + 1;
This fails for negative numbers.
int round_up(float y) {
return y + 0.99999999;
}
But let's use that to our advantage. float to int conversion is a truncate toward 0.0. Thus negative numbers are doing a "round up" or "ceiling" function. When we have a positive float, convert to int noting this is a "floor" function. Adjust when y is not an integer.
(Assume y within INT_MIN ... INT_MAX.)
int ceil(float y) {
if (y < 0) {
return y; // this does a ceiling function as y < 0.
}
int i = y; // this does a floor function as y >= 0.
if (i != y) i++;
return i;
}
void ceil_test(float y) {
printf("%f %d\n", y, ceil(y));
}
The first snippet works incorrectly for negative numbers. -3.5 will be come -3, not -4. To round values properly use
int round_number(float x)
{
if (x >= 0)
return x + 0.5f;
else
return x - 0.5f
}
Even that way it's still incorrect for 2 values. See Why does Math.round(0.49999999999999994) return 1?. Note that you need to use the f suffix to get the float literal, otherwise the operation will be done in double precision and then downcast back to float
For ceiling, adding 1 is enough
int ceiling(float x)
{
if (x < 0 || (int)x == x)
return x;
else
return x + 1.0f;
}
When x is an integer, e.g. x = 3.0 (or -3.0), it returns 3 (or -3). For x = 3.1 it returns 4, for x = -3.1 it returns -3

Manually implementing a rounding function in C

I have written a C program (which is part of my project) to round off a float value to the given precision specified by the user. The function is something like this
float round_offf (float num, int precision)
What I have done in this program is convert the float number into a string and then processed it.
But is there a way to keep the number as float itself and implement the same.
Eg. num = 4.445 prec = 1 result = 4.4
Of course there is. Very simple:
#include <math.h>
float custom_round(float num, int prec)
{
int trunc = round(num * pow(10, prec));
return (float)trunc / pow(10, prec);
}
Edit: it seems to me that you want this because you think you can't have dynamic precision in a format string. Apparently, you can:
int precision = 3;
double pie = 3.14159265358979323648; // I'm hungry, I need a double pie
printf("Pi equals %.*lf\n", precision, pie);
This prints 3.142.
Yes:
float round_offf(float num, int precision)
{
int result;
int power;
power = pow(10, precision + 1);
result = num * power;
if ((result % 10) > 5)
result += 10;
result /= 10;
return ((float)result / (float)power);
}

Resources