c floating point round down - c

If I run the following:
int tokenIdx=ERROR; //ERROR=8
tokens[tokenIdx] = 57; //tokens is of type int[]
int totalTokens = 100;
int percent = (int)((100.0 * tokens[tokenIdx])/(float)totalTokens);
printf("%d%\n",percent);
int percent2 = (int)(100.0*(tokens[tokenIdx]/(1.0*totalTokens)));
printf("%d%\n",percent2);
the output is:
57%
56%
Why is this happening?

Because 5700.0 and 100.0 can both be represented exactly as floating point numbers, and their ratio is exactly 57.0. On the other hand, 57.0/100.0 cannot be represented exactly as a floating pointer number, and multiplying it by 100.0 will not produced exactly 57.0. If it produces slightly less than 57.0 (as seems to be the case), then casting to (int), which truncates, will result in the integer 56.

Floating point rounding error. In your first case, you're doing a double divided by a float, in the second, it's a double divided by a double. The int conversion is throwing away the fractional portion, which in the second case is probably .999999999998 or something like it.
Lessons learned: floating point isn't precise, mind your conversions, watch your types
If you really honestly want an integer percentage, do:
int percent = 100 * value / total;
where value and total are both ints.
If you need more precision (say 10ths), consider doing it in thousands or and dividing down to float:
float percent = (1000 * value / total) / 10f;
Provided that 1000 * value won't overflow in your problem domain.

Related

Multiplying an int by an int to give a float is returning 0 language is C

lotacao_abs = (viagens[j].lotacao / 100) * navios[i].capacidade;
lotacao_abs is a float, viagens[j].lotacao is an int from a structure (yes, it's got the correct value I've checked), navios[i].capacidade is also an int (also has the correct value I've checked).
What's happening is that the value of lotacao_abs is always 0. The idea of this part of the code is to give me the absolute value instead of the percentage, viajens[j].lotacao has the percentage and navios[j].capacidade has the max capacity of the ship, lets say that the percentage is 68% and the max capacity is 34,000, then lotacao_abs should be 23,120, but it instead is 0.
The subexpression viagens[j].lotacao/100 is performing integer division. So if viajens[j].lotacao is less than 100 then the result will be 0.
One of the arguments has to have floating point type to perform floating point division. The simplest way to do this is to use 100.0 which is a floating point constant instead of 100 which is an integer constant.
lotacao_abs=(viagens[j].lotacao/100.0) * navios[i].capacidade;

Why casting double to int might give different results?

I am using fixed decimal point number (using uint16_t) to store percentage with 2 fractional digits. I have found that the way I am casting the double value to integer makes a difference in the resulting value.
const char* testString = "99.85";
double percent = atof(testString);
double hundred = 100;
uint16_t reInt1 = (uint16_t)(hundred * percent);
double stagedDouble = hundred * percent;
uint16_t reInt2 = (uint16_t)stagedDouble;
Example output:
percent: 99.850000
stagedDouble: 9985.000000
reInt1: 9984
reInt2: 9985
The error is visible in about 47% of all values between 0 and 10000 (of the fixed point representation). It does not appear at all when casting with stagedDouble. And I do not understand why the two integers are different. I am using GCC 6.3.0.
Edit:
Improved code snippet to demonstrate percent variable and to unify the coefficient between the two statements. The change of 100 into a double seems as a quality change that might affect the output, but it does not change a thing in my program.
Is percent a float? If so, look at what types you're multiplying.
reInt1 is double * float and stagedDouble is int * float. Mixing up floating point math can cause these types of rounding errors.
Changing the 100's to be both double or both int results in the same answer.
The reported behavior is consistent with percent being declared float, and the use of IEEE-754 basic 32-bit and 64-bit binary floating-point for float and double.
uint16_t reInt1 = (uint16_t)(100.0 * percent);
Since 100.0 is a double constant, this converts percent to double, performs a multiplication in double, and converts the result to uint16_t. The multiplication may have a very slight rounding error, up to ½ ULP of the double format, a relative error around 2−53.
double stagedDouble = 100 * percent;
uint16_t reInt2 = (uint16_t)stagedDouble;
Since 100 is an int constant, this converts 100 to float, performs a multiplication in float, and converts the result to uint16_t. The rounding error in the multiplication may be up to ½ ULP of the float format, a relative error around 2−24.
Since all of the values are near hundredths of an integer, a 50:50 ratio of errors up:down would make about half the results just under what is needed for the integer threshold. In the multiplications, all those with values that are 0, 25, 50, or 100 one-hundredths would be exact (because 25/100 is ¼, which is exactly representable in binary floating-point), so 96/100 would have rounding errors. If the directions of the float and double rounding errors behave as independent, uniform random variables, about half would round in different directions, producing different results, giving about 48% mismatches, which is consistent with the 47% reported in the question.
(However, when I measure the actual results, I get 42% differences between the float and double methods. I suspect that has something to do with the trailing bits in the float multiplication before rounding—the distribution might not act like a uniform distribution of two possibilities. It may be the OP’s code prepares the percent values in some way other than dividing an integer value by 100.)

How to round a float by casting as an int in C

So I am a second semester freshman in college. My teacher wants us to write a function that round a floating point number to the nearest hundredth. He said that we need to convert the floating point into an integer data type and then covert it back to a floating point. That's all he said. I have spent at least 5 hours trying different ways to do this.
This is my code so far:
#include <stdio.h>
int rounding(int roundedNum);
int main()
{
float userNum,
rounded;
printf("\nThis program will round a number to the nearest hundredths\n");
printf("\nPlease enter the number you want rounded\n>");
scanf("%f", &userNum);
rounded = rounding (userNum);
printf("%f rounded is %f\n", userNum, rounded);
return 0;
}
int rounding(int roundedNum)
{
return roundedNum;
}
Your instructor may be thinking:
float RoundHundredth(float x)
{
// Scale the hundredths place to the integer place.
float y = x * 100;
// Add .5 to cause rounding when converting to an integer.
y += .5f;
// Convert to an integer, which truncates.
int n = y;
// Convert back to float, undo scaling, and return.
return n / 100.f;
}
This is a flawed solution because:
Most C implementations use binary floating point. In binary floating-point, it is impossible to store any fractions that are not multiples of a negative power of two (½, ¼, ⅛, 1/16, 1/32, 1/64,…). So 1/100 cannot be exactly represented. Therefore, no matter what calculations you do, it is impossible to return exactly .01 or .79. The best you can do is get close.
When you perform arithmetic on floating-point numbers, the results are rounded to the nearest representable value. This means that, in x * 100, the result is, in generally, not exactly 100 times x. There is a small error due to rounding. This error cause push the value across the point where rounding changes from one direction to another, so it can make the answer wrong. There are techniques for avoiding this sort of error, but they are too complicated for introductory classes.
There is no need to convert to an integer to get truncation; C has a truncation function for floating-point built-in: trunc for double and truncf for float.
Additionally, the use of truncation in converting to integer compelled us to add ½ to get rounding instead. But, once we are no longer using a conversion to an integer type to get an integer value, we can use the built-in function for rounding floating-point values to integer values: round for double and roundf for float.
If your C implementation has good formatted input/output routines, then an easy way to find the value of a floating-point number rounded to the nearest hundred is to format it (as with snprintf) using the conversion specifier %.2f. A proper C implementation will convert the number to decimal, with two digits after the decimal point, using correct rounding that avoids the arithmetic rounding errors mentioned above. However, then you will have the number in string form.
Here are some hints:
Multiply float with "some power of 10" to ensure the needed precision numbers are shifted left
Cast the new value to a new int variable so the unwanted float bits are discarded
Divide the int by the same power of 10 but add use a float form of that (e.g 10.0) so integer gets converted to float and the new value is the correct value
To test, use printf with the precision (.2f)
The two most common methods of rounding are "Away From Zero" and "Banker's Rounding (To Even)".
Pseudo-code for Rounding Away From Zero
EDIT Even though this is pseudo-code, I should have included the accounting for precision, since we are dealing with floating-point values here.
// this code is fixed for 2 decimal places (n = 2) and
// an expected precision limit of 0.001 (m = 3)
// for any values of n and m, the first multiplicand is 10^(n+1)
// the first divisor is 10^(m + 1), and
// the final divisor is 10^(n)
double roundAwayFromZero(double value) {
boolean check to see if value is a negative number
add precision bumper of (1.0 / 10000) to "value" // 10000.0 is 10^4
multiply "value" by 1000.0 and cast to (int) // 1000.0 is 10^3
if boolean check is true, negate the integer to positive
add 5 to integer result, and divide by 10
if boolean check is true, negate the integer again
divide the integer by 100.0 and return as double // 100.0 is 10^2
ex: -123.456
true
-123.456 + (1.0 / 10000.0) => -123.4561
-123.4561 * 1000.0 => -123456.1 => -123456 as integer
true, so => -(-123456) => 123456
(123456 + 5) / 10 => 123461 / 10 => 12346
true, so => -(12346) => -12346
-12346 / 100.0 => -123.46 ===> return value
}
In your initial question, you expressed a desire for direction only, not the explicit answer in code. This is as vague as I can manage to make it while still making any sense. I'll leave the "Banker's Rounding" version for you to implement as an exercise.
Ok so I figured it out! thank yall for your answers.
//function
float rounding(float roundedNumber)
{
roundedNumber = roundedNumber * 100.0f + 0.5f;
roundedNumber = (int) roundedNumber * 0.01f;
return roundedNumber;
}
So pretty much if I entered 56.12567 as roundedNumber, it would multiply by 100 yielding 5612.567. From there it would add .5 which would determine if it rounds up. In this case, it does. The number would change to 5613.067.
Then you truncate it by converting it into a int and multiply by .01 to get the decimal back over. From there it returns the value to main and prints out the rounded number. Pretty odd way of rounding but I guess thats how you do it in C without using the rounding function.
Well, let's think about it. One thing that's helpful to know is that we can turn a float into an integer by casting:
float x = 5.4;
int y = (int) x;
//y is now equal to 5
When we cast, the float is truncated, meaning that whatever comes after the decimal point is dropped, regardless of its value (i.e. It always rounds towards 0).
So if you think about that and the fact that you care about the hundredths place, you could maybe imagine an approach that consists of manipulating your floating point number in someway such that when you cast it to an int you only truncate information you don't care about (i.e. digits past the hundredths place). Multiplying might be useful here.

How do I round off a Float value in C

I'm looking for function which can Round off a float value in C ,Suppose have number 0.1153846 should be rounded off till 6 decimal producing output as 0.115385
Though there is function in objective c like lroundf() but not sure how can use it in my context.
I'm on gcc compiler and any help would be much appreciated.
float f = 0.1153846;
f = floor(f * 1000000) / 1000000;
This should work.
You might want to do
double x = 0.1153846;
double rx = round (x * 1e6) * 1.e-6;
However, remember that IEEE 754 floating points are binary, with base 2 mantissa.
It's quite unusual for float to be a decimal type, that means that whatever you do, the result of the rounding will most often than not not be representable in a float and will be adjusted again to match a representable number.
If such a rounding is really needed for computational purpose, a floating point type is probably not the correct type to use.
If it is just for display purpose, use the control the printf family give you.
int precision = 3;
float num = 1.63322;
printf("%.*f",precision,num);

Multiplying two floats doesn't give exact result

I am trying to multiply two floats as follows:
float number1 = 321.12;
float number2 = 345.34;
float rexsult = number1 * number2;
The result I want to see is 110895.582, but when I run the code it just gives me 110896. Most of the time I'm having this issue. Any calculator gives me the exact result with all decimals. How can I achive that result?
edit : It's C code. I'm using XCode iOS simulator.
There's a lot of rounding going on.
float a = 321.12; // this number will be rounded
float b = 345.34; // this number will also be rounded
float r = a * b; // and this number will be rounded too
printf("%.15f\n", r);
I get 110895.578125000000000 after the three separate roundings.
If you want more than 6 decimal digits' worth of precision, you will have to use double and not float. (Note that I said "decimal digits' worth", because you don't get decimal digits, you get binary.) As it stands, 1/2 ULP of error (a worst-case bound for a perfectly rounded result) is about 0.004.
If you want exactly rounded decimal numbers, you will have to use a specialized decimal library for such a task. A double has more than enough precision for scientists, but if you work with money everything has to be 100% exact. No floating point numbers for money.
Unlike integers, floating point numbers take some real work before you can get accustomed to their pitfalls. See "What Every Computer Scientist Should Know About Floating-Point Arithmetic", which is the classic introduction to the topic.
Edit: Actually, I'm not sure that the code rounds three times. It might round five times, since the constants for a and b might be rounded first to double-precision and then to single-precision when they are stored. But I don't know the rules of this part of C very well.
You will never get the exact result that way.
First of all, number1 ≠ 321.12 because that value cannot be represented exactly in a base-2 system. You'll need an infinite number of bits for it.
The same holds for number2 ≠ 345.34.
So, you begin with inexact values to begin with.
Then the product will get rounded because multiplication gives you double the number of significant digits but the product has to be stored in float again if you multiply floats.
You probably want to use a 10-based system for your numbers. Or, in case your numbers only have 2 decimal digits of the fractional, you can use integers (32-bit integers are sufficient in this case, but you may end up needing 64-bit):
32112 * 34534 = 1108955808.
That represents 321.12 * 345.34 = 110895.5808.
Since you are using C you could easily set the precision by using "%.xf" where x is the wanted precision.
For example:
float n1 = 321.12;
float n2 = 345.34;
float result = n1 * n2;
printf("%.20f", result);
Output:
110895.57812500000000000000
However, note that float only gives six digits of precision. For better precision use double.
floating point variables are only approximate representation, not precise one. Not every number can "fit" into float variable. For example, there is no way to put 1/10 (0.1) into binary variable, just like it's not possible to put 1/3 into decimal one (you can only approximate it with endless 0.33333)
when outputting such variables, it's usual to apply many rounding options. Unless you set them all, you can never be sure which of them are applied. This is especially true for << operators, as the stream can be told how to round BEFORE <<.
Printf also does some rounding. Consider http://codepad.org/LLweoeHp:
float t = 0.1f;
printf("result: %f\n", t);
--
result: 0.100000
Well, it looks fine. Why? Because printf defaulted to some precision and rounded up the output. Let's dial in 50 places after decimal point: http://codepad.org/frUPOvcI
float t = 0.1f;
printf("result: %.50f\n", t);
--
result: 0.10000000149011611938476562500000000000000000000000
That's different, isn't it? After 625 the float ran out of capacity to hold more data, that's why we see zeroes.
A double can hold more digits, but 0.1 in binary is not finite. Double has to give up, eventually: http://codepad.org/RAd7Yu2r
double t = 0.1;
printf("result: %.70f\n", t);
--
result: 0.1000000000000000055511151231257827021181583404541015625000000000000000
In your example, 321.12 alone is enough to cause trouble: http://codepad.org/cgw3vUKn
float t = 321.12f;
printf("and the result is: %.50f\n", t);
result: 321.11999511718750000000000000000000000000000000000000
This is why one has to round up floating point values before presenting them to humans.
Calculator programs don't use floats or doubles at all. They implement decimal number format. eg:
struct decimal
{
int mantissa; //meaningfull digits
int exponent; //number of decimal zeroes
};
Ofc that requires reinventing all operations: addition, substraction, multiplication and division. Or just look for a decimal library.

Resources