C arithmetic, modulus - c

So I have this problem I'm working on where I must determine the cost for time spent at a go kart track; they charge by the hour and if you spend 30 minutes or more for a specific hour, you are charged the full amount. Note: I am not looking for someone to just answer my hw for me, much like I don't think anyone here would do so.
I will now post my source code:
#include <math.h>
int main(){
float price;
int minutes;
int hours;
int total_cost;
printf("How much does this go-kart location charge per hour?\n");
scanf("%f", &price);
printf("How many minutes can you spend there?\n");
scanf("%d", &minutes);
hours= minutes/60;
total_cost=hours * price;
printf("Your total will be $%d" ,&total_cost);
return 0;
}
..................................................................................
My problem is that
. I'm not sure how to accurately calculate someones time spent, and thus the cost will be wrong. If someones spends 1.5 hours at this place, they are billed for 2 hours.And likewise if someone spends just 30 min. they are billed for 1 hour in full.
Part of me believes I am to use the modulus operator in order to round up the remainder but I'm not sure how to do so.60 minutes in an hour and I spend 30 minutes at this track, 60 % 30 would be the time spent. But this returns a remainder of 30, and spending 30 minutes would mean I pay full price for 1 hour.
Again I'm not looking for someone to answer my hw for me, it would serve me no purpose , just some general help on how to calculate a number that must always be rounded up from the half of the hour and onwards.
Thanks to anyone and everyone who helps, or just stops by.
Update; SO I added an if else statement to my problem, and it seems to be working. I'll post the updated source code below.
................................................................................
This appears to work based on some trial runs i've done, I'll have to edit the output for 2 decimal place(%.2f, I think, to make it look nicer, thanks to all of you for your help, I'm new to programming in C, and it confuses me deeply, but It's important to me to learn this, not just for some grade, so thanks for being so helpful.

If you can use floating-point types, the simplest thing to do is just round to the nearest integer:
int billable_hours(int minutes) {
return (int)round(minutes / 60.);
}
it's worth reading up on the rounding modes to verify this will do what you need.
There's a trick to avoid worrying about rounding modes, which is to add a bias so that simply rounding down does what you need:
int billable_hours(int minutes) {
return (int)floor(0.5 + minutes / 60.);
}
But that this works the same if we stick with integers (integer division discards the fractional part, effectively rounding towards zero):
int billable_hours(int minutes) {
return (minutes + 30) / 60;
}
because any fractional hour >= 30 minutes, we force up to the next whole hour before discarding the fractional part.
Notes:
these will behave differently with negative inputs. Not (hopefully) relevant here, but worth being aware of
be aware of type promotions: the literal 60. is a double, while 60 would be an integer. When you write int / double, it is promoted to double / double instead, so you don't have to cast. The division in the third function is still integer division, though.
by the simplest thing, I mean the simplest thing to type and/or read. Computationally the third is by far the simplest.

Try this,
int extra;
hours= minutes/60;
extra = minutes % 60;
if(extra >= 30)
hours += 1;
total_cost=hours * price;
printf("Your total will be $%d" ,total_cost);
hours = minutes/60 gives the number of full hours, since hours is an integer variable. hours%60 gives you the extra minutes spent. And there is no need for an & before total_cost in the printf statement.

You are rounding times to the nearest integer. When you do integer (modulo N) arithmetic, one way to round things to the nearest integer is to add N/2 to the original number of minutes (this is equivalent to the int(x + 0.5) problem to arithmetic (module 1)), so when you integer divide by N, you'll get results rounded to the nearest integer. Try hours_to_charge = (minutes_run + 30) / 60; and you'll get the desired results.
Example
So, if you have, for example 37 minutes and want to know how many hours to charge, just add 30 min to that (getting 67) and then divide by 60 (getting one hour)
But, be carefull that for times of under 30 minutes you are going to charge 0 to the cart runners.

Just cast minutes to a float, and than round the number using ceil() and floor(). A very common way of doing this is defining a macro called ROUND to accomplish this:
#define ROUND(x) ((x - floor(x) >= 0.5) ? ceil(x) : floor(x))
hours = ROUND((float)minutes/(float)60);
This will turn your hours into billable hours, and the rest of your code will work as coded.

Related

Finding whether an interval contains at least one integer without math.h

For a class project I need to split some audio clips in smaller sections, for which we are provided a min length and a max length, to figure out whether this is possible, I do the following:
a = length/max
b = length/min
mathematically I figured that [a,b] contains at least one integer if ⌊b⌋ >= ⌈a⌉, but I can't use math.h for floor() and ceil(). Since a and b are always positive I can use type casting for floor(), but I am at a loss at how to do ceil(). I thought about using ((int)x)+1 but that would round integers up which would break the formula.
I would like either a way to do ceil() which would solve my problem, or another way to check whether an interval contains at least one integer.
You don't need the math.h to perform floor. Please look at the following code:
int length=5,min=2,max=3; // only an example of inputs.
int a = length/max;
int b = length/min;
if(a!=b){
//there is at least one integer in the interval.
}else{
if(length % min==0 || length % max==0 ){
//there is at least one integer in the interval.
}else{
//there is no integer in the interval.
}
}
The result for the above example will be that there is an integer in the interval.
You can also perform ceil without using math.h as following:
int a;
if(length % max == 0){
a = length / max;
}else{
a = (length / max) + 1;
}
If I understood you question right, I guess, you can do ceil(a) in this case, and then check if the result is less then b. Thus, for example, for interval [1.3, 3.5], ceil(1.3) will return 2, which fits into this interval.
UPD
Also you could do (b - a). If it's > 1, there's for sure at least one integer between them.
There is a general trick in programming that will come in hand if you ever find yourself programming Apple Basic, or any other language where floating point math is supported.
You can "round" a number by addition, then truncation, as follows:
x = some floating value
rounded_x = int(x + roundoff_amount)
Where roundoff_amount is the difference between the lowest fraction to round up, and 1.
So, to round at .5, your round_off would be 1 - .5 = .5, and you would do int(x + .5). If x is .5 or .51 then the result becomes 1.0 or 1.01 and int() takes that to 1. Obviously, if x is higher, then you still get rounded to 1, until x becomes 1.5 when rounding takes it to 2. To round upwards starting at .6, your roundoff amount would be 1 - .6 = .4, and you would do int(x + .4), etc.
You can do a similar thing to get ceil behavior. Set your roundoff_amount to be 0.99999... and do the round. You can choose your value to provide a "nearby" window, since floats have some inaccuracy inherent that might prevent getting a perfectly integer value after adding fractions.

C while loop tricky exceptions [duplicate]

This question already has answers here:
Why are floating point numbers inaccurate?
(5 answers)
Closed 5 years ago.
I am a beginner and this is (a simplified version of) part of a code I am writing:
1.prompt user to input a number (float dollar amount), lets say user will only key in amount which are multiples of 0.05 ;
2.calculate the (int)number of nickels in that dollar amount.
int main(void)
{
float amount = 0;
printf("$ ");
amount = get_float();
int n = 0;
while ((amount - 0.05) >= 0)
{
amount -= 0.05;
n ++;
}
printf("%i nickels\n", n);
}
It works for any amount <=0.3 or >=1.2 (so $2 has 40 nickels, and $0.30 has 6 nickels);
but one nickel less for any amount between/including 0.35 and 1.15 (so $0.35 has 6 nickels, and $1 has 19 nickels)
I did step by step printing, and it turns out that for any amount between 0.35 and 1.15, the program stops at the last 0.050000, instead of going back to the loop and loop it one last time.
What went wrong? Please help... Thanks so much for your time!
You are hitting up against floating point rounding.
Floating points are never exactly accurate, try calculating
printf("one third 'ish' = %6.20lf\n", (double) 1.0/ (double) 3.0);
Look at the answer, it's not quite accurate. :)
Your best bet is to accept the input, convert it to an integer (ie, cents) by multiplying by 100, removing any decimals using round() and assigning to a long.
#include <math.h> // to get the round() function
.
.
.
long amountInCents = round(amount * 100);
Then, change your code to compare against 5 cents, not $0.05, and to reduce by 5 cents, not $0.05
This way, you get rid of all 'rounding' issues.
EDIT: cmaster showed me that using floor() didn't work, using $0.57 as input, when using 'double' variables (not float), $0.57 converted to (long) 56! He supplied code and I couldn't believe my eyes!
The is no bug in your code in the strictest sense as the underlying reasoning is correct; however note that the value 0.35 cannot be represented exactly in the float datatype, the same holds for 0.05; as the division (what basically is the sematics of the code in the question) is implemented via repeated subtraction, the error caused by the inability to exactly represent the desired values accumulates. The result is that the number of subtractions is different from the analytically expected result, as the termination condition is reached too soon. The float datatype is not suitable for financial calculations, even in such a very small everyday example.
This is terrible, but it is a matter of fact.
I found a fix. This is working
enter code here
while ((amount - 0.0499) >= 0)
{
amount -= 0.05;
n ++;
}
while scanning .35 amount as float the actual amount value is 0.3499

In C, why is the ratio 10.0/100 different from 0.1? [duplicate]

This question already has answers here:
Why Floating point numbers cant be compared? [duplicate]
(7 answers)
Closed 7 years ago.
This is a simple question and I searched the forums, but couldn't find an answer (I found one about Log but I don't think there is a rounding error here).
I wrote a program to determine the value of a fine for a range of expired products, but when the ratio is exact, the program will return the next fine category, ignoring the = sign in the conditional.
The program must return the following fines:
0 if no product is expired.
100 if up to 10% of products are expired.
10000 if more than 10% of products and up to 30% are expired.
100000 if more than 30% of products are expired.
This is the code I wrote:
#include <stdio.h>
int calculate_fine(int ncheckedproducts, int nexpiredproducts)
{
int fine;
float ratio;
ratio=(float)nexpiredproducts/ncheckedproducts;
if(nexpiredproducts==0)
fine=0;
else
if(ratio<=0.1)
fine=100;
else
if(ratio<=0.3)
fine=10000;
else
fine=100000;
return fine;
}
int main(void)
{
int ncheckedproducts, nexpiredproducts, fine;
printf("Type number of checked and expired products\n");
scanf("%d %d", &ncheckedproducts, &nexpiredproducts);
fine=calculate_fine(ncheckedproducts, nexpiredproducts);
printf("The fine is: %d\n", fine);
return 0;
}
But for values of 100 and 10, and 100 and 30, exactly 10% and 30% of expired products respectively, the program will return the wrong fine.
The teacher failed to explain me why, and corrected me to the following function:
int calculate_fine(int ncheckedproducts, int nexpiredproducts)
{
int fine;
if(nexpiredproducts==0)
fine=0;
else
if(nexpiredproducts<=0.1*ncheckedproducts)
fine=100;
else
if(nexpiredproducts<=0.3*ncheckedproducts)
fine=10000;
else
fine=100000;
return fine;
}
However, I wish to know why the first 10% ratio is greater than 0.1, and why I cannot use this approach.
This most probably is a rounding issue, but a different than you might think: Many finite decimal fractions do not have a finite binary fraction representation. Thus, some rounding the the closest number representable as a floating point number of the given type happens.
What you're dealing with is are the fine-grained aspects of floating point numbers:
Computers save floating point numbers in a binary format. Your float is probably a IEEE-754 single precision floating point number.
In those formats, you can typically represent only numbers exactly that are only a sum of a very limited amount of powers of two; for example, 0.75 is 2-1 + 2-2 and can hence be exactly reconstructed. In your case, you try to divide 100 = 26 + 25 + 22 by 3 = 21+20 and hope you get exactly the same result as 0.3 = 2-2+ 2-5+ 2-9+ 2-10+ 2-13+ ...
That won't happen.

adding/subtracting floats/ints linux C

(can skip this part just an explanation of the code below. my problems are under the code block.)
hi. i'm trying to algro for throttling loop cycles based on how much bandwidth the linux computer is using. i'm reading /proc/net/dev once a second and keeping track of the bytes transmitted in 2 variables. one is the last time it was checked the other is the recent time. from there subtracts the recent one from the last one to calculate how many bytes has been sent in 1 second.
from there i have the variables max_throttle, throttle, max_speed, and sleepp.
the idea is to increase or decrease sleepp depending on bandwidth being used. the less bandwidth the lower the delay and the higher the longer.
i am currently having to problems dealing with floats and ints. if i set all my variables to ints max_throttle becomes 0 always no matter what i set the others to and even if i initialize them.
also even though my if statement says "if sleepp is less then 0 return it to 0" it keeps going deeper and deeper into the negatives then levels out at aroung -540 with 0 bandwidth being used.
and the if(ii & 0x40) is for speed and usage control. in my application there will be no 1 second sleep so this code allows me to limit the sleepp from changing about once every 20-30 iterations. although im also having a problem with it where after the 2X iterations when it does trigger it continues to trigger every iteration after instead of only being true once and then being true again after 20-30 more iterations.
edit:: simpler test cast for my variable problem.
#include <stdio.h>
int main()
{
int max_t, max_s, throttle;
max_s = 400;
throttle = 90;
max_t = max_s * (throttle / 100);
printf("max throttle:%d\n", max_t);
return 0;
}
In C, operator / is an integer division when used with integers only. Therefore, 90/100 = 0. In order to do floating-point division with integers, first convert them to floats (or double or other fp types).
max_t = max_s * (int)(((float)throttle / 100.0)+0.5);
The +0.5 is rounding before converting to int. You might want to consider some standard flooring functions, I don't know your use case.
Also note that the 100.0 is a float literal, whereas 100 would be an intger literal. So, although they seem identical, they are not.
As kralyk pointed out, C’s integer division of 90/100 is 0. But rather than using floats you can work with ints… Just do the division after the multiplication (note the omission of parentheses):
max_t = max_s * throttle / 100;
This gives you the general idea. For example if you want the kind of rounding kralyk mentions, add 50 before doing the division:
max_t = (max_s * throttle + 50) / 100;

Measuring time taken by a function: clock_gettime

I am trying to measure how long a function takes.
I have a little issue: although I am trying to be precise, and use floating points, every time I print my code using %lf I get one of two answers: 1.000... or 0.000... This leads me to wonder if my code is correct:
#define BILLION 1000000000L;
// Calculate time taken by a request
struct timespec requestStart, requestEnd;
clock_gettime(CLOCK_REALTIME, &requestStart);
function_call();
clock_gettime(CLOCK_REALTIME, &requestEnd);
// Calculate time it took
double accum = ( requestEnd.tv_sec - requestStart.tv_sec )
+ ( requestEnd.tv_nsec - requestStart.tv_nsec )
/ BILLION;
printf( "%lf\n", accum );
Most of this code has not been made by me. This example page had code illustrating the use of clock_gettime:
Could anyone please let me know what is incorrect, or why I am only getting int values please?
Dividing an integer by an integer yields an integer. Try this:
#define BILLION 1E9
And don't use a semicolon at the end of the line. #define is a preprocessor directive, not a statement, and including the semicolon resulted in BILLION being defined as 1000000000L;, which would break if you tried to use it in most contexts. You got lucky because you used it at the very end of an expression and outside any parentheses.
( requestEnd.tv_nsec - requestStart.tv_nsec ) is of integer type, and is always less than BILLION, so the result of dividing one by the other in integer arithmetic will always be 0. You need to cast the result of the subtraction to e.g. double before doing the divide.
Note that (requestEnd.tv_nsec - requestStart.tv_nsec) can be negative, in which case you need to subtract 1 second from the tv_sec difference and add one BILLION to the tv_nsec difference.
I know the question was posted long ago, but I still don't see the answer which would suggest you to "convert" elapsed time into nanoseconds (or milliseconds) and not into seconds as in your code sample.
The sample code fragment to illustrate the idea:
long long accum = ( requestEnd.tv_nsec - requestStart.tv_nsec )
+ ( requestEnd.tv_sec - requestStart.tv_sec ) * BILLION;
This way you can avoid floating point arithmetic, which may be heavy for some platforms...

Resources