Simple division of odd numbers not working in C programming - c

I'm sure I'm missing something extremely simply since I'm very new to this, but for some reason when I divide an odd number by 2 and then multiply the result, the program will only multiply by the number rounded down, for example when I divide 5 by 2 and then multiply that, it only multiplies it by 2, not even 2.5. What I am eventually trying to do is have it so it rounds up so that dividing 5 by 2 would become 3, but for whatever reason it rounds down now automatically. Here's my code:
#include <stdio.h>
#include <math.h>
int main() {
int num_containers;
float price, total, num_half;
printf("What is the cost of one container?\n");
scanf("%f", &price);
printf("How many containers are you buying?\n");
scanf("%d", &num_containers);
num_half = num_containers / 2;
total = num_half * price;
if(num_containers % 2 == 0)
printf("The total cost is $%.2f.\n", num_containers / 2 * price);
else
printf("The total cost is $%f.\n", num_containers / 2 * price);
return 0;
}

num_containers is defined as int, when you divide it by 2 it is rounded down.

The expression
num_containers / 2;
is evaluated as integer division since both operands are integers, resulting in an integer. There's no way to represent the remaining 0.5 in an integer, so it is lost.
For comparison, the expression
0.5 * num_containers;
includes a floating-point literal, so num_containers is promoted to a double first, and the result is a double (num_containers / 2.0 does the same).
Since everything apart from num_containers is a float, skipping the intermediate value would have worked:
total = num_containers * price / 2;
Note, in order to force rounding up, you can either do it explicitly with ceil
total = ceil(num_containers / 2.0) * price;
or stay in integer land and simply add one:
int more_than_half = (num_containers + 1) / 2;

The variable num_containers is an integer, and so the expression num_containers / 2 will resolve to a rounded integer value. If you declare it as float num_containers, you should get the desired result, or you can cast it as a floating point value whenever you use it in an expression. For example:
num_half = (float) num_containers / 2;

If you want a rounded division in integer arithmetic, add an adjustment before doing the divide. For example to divide by 10 and round, add 5 first. In your case of dividing by 2
num_half = (num_containers + 1) / 2;
Which will round 5 / 2 up to 3.

It's because num_containers is defined as an int. If you do operations including an int and a float, the result will become a float. You're dividing an int by an int, so the result is an int.
If you want a float result, first cast num_containers to a float, or, if you're always dividing by the literal '2', change it to 2.0f.

Related

How to round up in C

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void)
{
const double TAX = 0.13;
double small = 17.96;
double subTotal = small * 6;
double taxes = subTotal * TAX;
printf("j SubTotal: %9.4lf Tax: %9.4lf \n", (double)subTotal, (double)taxes);
return 0;
}
The required output is
SubTotal: 107.7600 Tax: 14.0100 should come out.
My output is:
SubTotal: 107.7600 Tax: 14.0088
What should I do?
The solution is to not ever use floating point types for currency.
If you have a decimal type available, use it.
If you don't, write one.
Or, at a minimum, use long integers to store cents.
If you want to round to two decimal places, multiply by one hundred add one half, truncate to an int and then divide by one hundred. Like,
double round(double v) {
return ((int)(v * 100 + .5)) / 100.;
}
Then you can call that like
double taxes = round(subTotal * TAX);
And I get (with no other changes)
j SubTotal: 107.7600 Tax: 14.0100
C provides useful rounding functions rint(), round(), nearby(), llround() that well handle rounding corner cases.
To round to the nearest 100th, scale the value by /100.0, round and scale back.
#include <math.h>
double value = ...;
value *= 100.0;
value = round(value); // or rint(), nearby()
value /= 100.0;
At this point, value may not exactly be of the form ddd.dd but will be the closest double to that form. Printing with "%.4f" will then print to the closest 0.0001.
printf("%9.4lf\n", value);
Alternatively, take money and round to the smallest monetary unit - suppose OP wants to the nearest cent (0.01).
long long value_cents = llround(value * 100.0);
printf("%lld.%02d00", amount / 100, abs(amount % 100));
It’s a weird requirement to display four decimal places while rounding to two, but you can satisfy it by displaying two decimal places and hard-coding the characters 00 after it:
printf("j SubTotal: %9.2f00 Tax: %9.2f00 \n", subTotal, taxes);
Do not use floating point numbers for currency because they are tricky and inexact in many cases. Here is a working solution that gives you the exact output you want, but you should know it is strange to print more than two digits after the decimal point if those extra digits are always zero.
The + 99 in the code below is the trick you need to make the calculation always round up, instead of rounding down which is the normal behavior of unsigned integer division.
#include <stdio.h>
#include <stdint.h>
void print_money_with_strange_format(uint64_t amount)
{
printf("%llu.%02llu00", amount / 100, amount % 100);
}
int main(void)
{
uint64_t tax_rate = 13;
uint64_t small = 1796;
uint64_t subtotal = small * 6;
uint64_t tax = (subtotal * tax_rate + 99) / 100;
printf("SubTotal: ");
print_money_with_strange_format(subtotal);
printf(" Tax: ");
print_money_with_strange_format(tax);
printf("\n");
}
If you want to round the output to two decimals, but still producing four on output, just use
printf("%9.2f00", value);
and the value will be rounded to two decimals, and two zeros will be appended to it. But, why the computer should round 88 to 100 in a calculation, when you have not commanded it to round numbers at some place?
To round a number when the first decimal is over .5, you can just add 0.5 and then truncate the result. In case you want to do it at some position, just multiply the number by the required power of ten (in this case 100) and after the truncation, divide it again by that power(100), as proposed by other answers.

Save float result number to third digit, no rounding in C

How to round result to third digit after the third digit.
float result = cos(number);
Note that I want to save the result up to the third digit, no rounding. And no, I don't want to print it with .3f, I need to save it as new value;
Example:
0.00367 -> 0.003
N.B. No extra zeroes after 3 are wanted.
Also, I need to be able to get the 3rd digit. For example if it is 0.0037212, I want to get the 3 and use it as an int in some calculation.
0.00367 -> 0.003
A float can typically represent about 232 different values exactly. 0.00367 and 0.003 are not in that set.
The closest float to 0.00367 is 0.0036700000055134296417236328125
The closest float to 0.003__ is 0.0030000000260770320892333984375
I want to save the result up to the third digit
This goal needs a compromise. Save the result to a float near a multiple of 0.001.
Scaling by 1000.0, truncating and dividing by 1000.0 will work for most values.
float y1 = truncf(x * 1000.0f) / 1000.0f;
The above gives a slightly wrong answer with some values near x.xxx000... and x.xxx999.... Using higher precision can solve that.
float y2 = (float) (trunc(x * 1000.0) / 1000.0);
I want to get the 3 and use it as an int in some calculation.
Skip the un-scaling part and only keep 1 digit with fmod().
int digit = (int) fmod((trunc(x * 1000.0), 10);
digit = abs(digit);
In the end, I suspect this approach will not completely satisfy OP's unstated "use it as an int in some calculation.". There are many subtitles to FP math, especially when trying to use a binary FP, as are most double, in some sort of decimal way.
Perhaps the following will meet OP's goal, even though it does some rounding.:
int third_digit = (int) lround(cos(number)*1000.0) % 10;
third_digit = abs(third_digit);
You can scale the value up, use trunc to truncate toward zero, then scale down:
float result = trunc(cos(number) * 1000) / 1000;
Note that due to the inexact nature of floating point numbers, the result won't be the exact value.
If you're looking to specifically extract the third decimal digit, you can do that as follows:
int digit = (int)(result * 1000) % 10;
This will scale the number up so that the digit in question is to the left of the decimal point, then extract that digit.
You can subtract from the number it's remainder from division by 0.001:
result -= fmod(result, 0.001);
Demo
Update:
The question is updated with very conflicting requirements. If you have an exact 0.003 number, there will be infinite numbers of zeroes after it, and it is a mathematical property of numbers. OTOH, float representation cannot guarantee that every exact number of 3 decimal digits will be represented exactly. To solve this problem you will need to give up on using the float type and switch to a some sort of fixed point representation.
Overkill, using sprintf()
double /* or float */ val = 0.00385475337;
if (val < 0) exit(EXIT_FAILURE);
if (val >= 1) exit(EXIT_FAILURE);
char tmp[55];
sprintf(tmp, "%.50f", val);
int third_digit = tmp[4] - '0';

math operations with different types in C

I'm very new to C, and I'm trying to write a simple program that calculates the amount of taxes owed based on gross income and tax rate. I have no idea why owedTax prints as 0 with the following inputs.
#include <stdio.h>
int main()
{
// get user's AGI
double userAGI;
printf("enter agi:\n");
scanf("%lf",&userAGI)
// get tax rate
int taxRate;
printf("enter desired tax rate:\n");
scanf("%d",&taxRate);
// calculate owed tax
double owedTax = (taxRate / 100) * userAGI;
printf("%lf\n",owedTax);
return 0;
}
Ouput:
enter agi:
100
enter desired tax rate:
10
0.0000000
Why does owedTax print as 0?
The problem is here:
double owedTax = (taxRate / 100) * userAGI;
Since taxRate is an integer, and 100 is an integer, it performs integer division, with the result being integer 0. It then converts this result to double and multiplies it by userAGI. To fix it, you just need to force it to do a floating divide, as follows:
double owedTax = (taxRate / 100.0) * userAGI;
Since 100.0 is a double constant, it will convert taxRate to double before performing the division.
Change:
// calculate owed tax
double owedTax = (taxRate / 100.0) * userAGI;
You have to use 100.0 instead 100 to get the desired result.
If you divide two integers, an integer division is performed, discarding fractional part.
Fix
double owedTax = (taxRate / 100) * userAGI;
to
double owedTax = (taxRate / 100.0) * userAGI;
^^^^^
or
double owedTax = ((double)taxRate / 100) * userAGI;
^^^^^^^^
The problem is that in C and C++, when you divide two integers, an integer division is performed, that returns the integer part of the result, with the fractional part discarded.
Look:
10 / 100 = 0.1 in algebra. Discard the fractional part -> 0 remains.
If you want to divide two integers and get an exact floating-point result, explicitly cast one of the integers to a floating-point type. A common error indeed! (Done it myself many times.)
For the reference, I'm linking this excellent discussion here on SO:
What is the behavior of integer division in C?

Moving decimal place to right in c

I'm new to C and when I run the code below, the value that is put out is 12098 instead of 12099.
I'm aware that working with decimals always involves a degree of inaccuracy, but is there a way to accurately move the decimal point to the right two places every time?
#include <stdio.h>
int main(void)
{
int i;
float f = 120.99;
i = f * 100;
printf("%d", i);
}
Use the round function
float f = 120.99;
int i = round( f * 100.0 );
Be aware however, that a float typically only has 6 or 7 digits of precision, so there's a maximum value where this will work. The smallest float value that won't convert properly is the number 131072.01. If you multiply by 100 and round, the result will be 13107202.
You can extend the range of your numbers by using double values, but even a double has limited range. (A double has 16 or 17 digits of precision.) For example, the following code will print 10000000000000098
double d = 100000000000000.99;
uint64_t j = round( d * 100.0 );
printf( "%llu\n", j );
That's just an example, finding the smallest number is that exceeds the precision of a double is left as an exercise for the reader.
Use fixed-point arithmetic on integers:
#include <stdio.h>
#define abs(x) ((x)<0 ? -(x) : (x))
int main(void)
{
int d = 12099;
int i = d * 100;
printf("%d.%02d\n", d/100, abs(d)%100);
printf("%d.%02d\n", i/100, abs(i)%100);
}
Your problem is that float are represented internaly using IEEE-754. That is in base 2 and not in base 10. 0.25 will have an exact representation, but 0.1 has not, nor has 120.99.
What really happens is that due to floating point inacuracy, the ieee-754 float closest to the decimal value 120.99 multiplied by 100 is slightly below 12099, so it is truncated to 12098. You compiler should have warned you that you had a truncation from float to in (mine did).
The only foolproof way to get what you expect is to add 0.5 to the float before the truncation to int :
i = (f * 100) + 0.5
But beware floating point are inherently inaccurate when processing decimal values.
Edit :
Of course for negative numbers, it should be i = (f * 100) - 0.5 ...
If you'd like to continue operating on the number as a floating point number, then the answer is more or less no. There's various things you can do for small numbers, but as your numbers get larger, you'll have issues.
If you'd like to only print the number, then my recommendation would be to convert the number to a string, and then move the decimal point there. This can be slightly complicated depending on how you represent the number in the string (exponential and what not).
If you'd like this to work and you don't mind not using floating point, then I'd recommend researching any number of fixed decimal libraries.
You can use
float f = 120.99f
or
double f = 120.99
by default c store floating-point values as double so if you store them in float variable implicit casting is happened and it is bad ...
i think this works.

Why does this integer division yield 0?

Could someone tell me why the following code is outputting 0 at the marked line?
It seems as if everything is correct but then when I try to get the result near the end it's giving me 0 each time.
#include <stdio.h>
int main() {
// Gather time-lapse variables
int frameRate, totalLengthSecs;
printf("How many frames per second: ");
scanf("%i", &frameRate);
printf("--> %i frames confirmed.", frameRate);
printf("\nDesired length of time-lapse [secs]: ");
scanf("%i", &totalLengthSecs);
printf("--> %i seconds confirmed.", totalLengthSecs);
int totalFrames = frameRate * totalLengthSecs;
printf("\nYou need %i frames.", totalFrames);
// Time-lapse interval calculation
int timeLapseInterval = totalLengthSecs / totalFrames;
printf("\n\n%i", timeLapseInterval); // <-- this prints 0
return 0;
}
In short: Integer division truncates
You need the following:
double timeLapseInterval = (double) totalLengthSecs / (double)totalFrames;
printf("\ntimeLapseInterval : %f \n", timeLapseInterval);
You are performing integer math.
Math between two integers will produce an integer. And the result will be rounded towards zero.
This line:
totalLengthSecs / totalFrames;
Is likely producing a result that's between 0 and 1. And getting rounded to 0
You are printing integers and therefore it will round down the value.
timeLapseInterval / totalFrames will be (1 / frameRate) which will be < 1 unless frameRate is 1 (or 0 in which case you have an error dividing by 0)
When you divide 2 numbers in C and the denominator is integer, the compiler intends it as an integer division. Therefore, if you divide 1 divided 2, it returns zero and not 0.5
Moreover, your output variable is an integer too, hence, if you expect decimal outputs, you won't get it.
You can fix it by doing:
float timeLapseInterval = totalLengthSecs / (float)totalFrames;
printf("\n\n%f", timeLapseInterval);
I hope this helps

Resources