So this program is supposed to estimate hourly temperatures throughout a day after being given the daily high, low and the hour which the low is expected. I am having problems calling up my functions inside the main function. I don't really understand how I am supposed to get specific information from the functions, and use it in place of a variable in my main function. I'm also having trouble grasping the idea of parameters and arguments. I'm sure I've messed up in more than one place here, but I'm mostly concerned about the functions right now. Any help would be appreciated.
#include <stdio.h>
#include <math.h>
#define PI 3.14159
double getFahrTemp(double high, double low, int hour);
double fahr2cels( double fahr );
double cels2kelv( double cels );
double fahr2rank( double fahr );
double getDailyHigh()
{
int high;
printf("Enter the daily high temperature <F>:\n");
scanf("%d",&high);
return high;
}
double getDailyLow()
{
int low;
printf("Enter the daily low temperature <F>:\n");
scanf("%d",&low);
return low;
}
int getLowHour()
{
int lowHour;
printf("Enter the time of the daily low temperature:\n");
scanf("%d",&lowHour);
return lowHour;
}
double getFahrTemp(double high, double low, int hour)
{
return (high-low)/2 * sin(2*PI/24 * hour + 3.0/2.0 * PI) + (high+low)/2;
}
double fahr2cels( double fahr )
{
double cels;
cels = fahr - 32 / 1.8;
}
double cels2kelv( double cels )
{
double kelv;
kelv = cels + 273;
}
double fahr2rank ( double fahr )
{
double rank;
rank = fahr + 459.67;
}
int main(getDailyHigh, getDailyLow, getLowHour, getFahrTemp)
{
int hour, time;
printf ("Temperature Scale Conversion Chart:\n")
printf ("TIME FAHR CELSIUS KELVIN RANKINE")
getDailyHigh();
getDailyLow();
getLowHour();
do
{
int time, hour=1;
time = (hour + lowHour) % 12;
getFahrTemp(getDailyHigh(), getDailyLow(), hour)
fahr2cels
cels2kelv
fahr2rank
printf ("%d:00 %2.2d %2.2d %3.2d %3.2d\n", time, fahr, cels, kelv, rank;
hour = hour++;
}
while (hour <= 24);
}
I don't really understand how I am
supposed to get specific information
from the functions, and use it in
place of a variable in my main
function. I'm also having trouble
grasping the idea of parameters and
arguments.
Do you understand the concept of a function in mathematics? For example, the equation to convert celcius to fahrenheit is:
°C = (°F − 32) × 5⁄9
One can write this as a mathematical function:
f(x) = (x - 32) × 5⁄9
The function f accepts a single argument called x and returns (x - 32) × 5⁄9. To "use" the function, you would write:
y = f(x)
Given a variable x, you can assign the result of function f to a variable y.
Once you understand this, you can easily see how it transfers to programming:
double fahr2cels(double f)
{
return (f - 32) * 5 / 9;
}
Calling the function even looks like "how math is done":
double celcius = fahr2cels(fahrenheit);
In the same way you can have multivariable functions in math, you can have functions that accept multiple parameters. You can even have functions that accept no parameters!
double getFahrTemp(double high, double low, int hour)
{
return (high-low)/2 * sin(2*PI/24 * hour + 3.0/2.0 * PI) + (high+low)/2;
}
The syntax for calling a function is fairly consistent:
// Call the function getFahrTemp(), passing three parameters.
// The variable fahrtemp receives the result of the function call.
double fahrtemp = getFahrTemp(high, low, hour);
There are some important differences I must take note of in this math analogy - functions in C can have side effects (they affect program state in some way outside the function). Also, parameters that you pass are always copied.
The problem is in this section:
fahr2cels
cels2kelv
fahr2rank
You need to pass the parameter specified:
degCel = fahr2cels(degF);
Some basic rules to help you understand:
All C statements end in a semicolon (;).
(none of your functions in the block cited had a semicolon at the end...)
Look to the function definition for information on what to pass
double fahr2cels( double fahr );
Says that the function takes 1 variable, which must be a double (floating point number)
Look to the function definition for information on what the function returns
All functions return only 1 (or zero) values. But the type of that one value is important.
double fahr2cels( double fahr );
Says that the function returns a value that is a double.
Take that information together, and make some changes to your code:
double dailyHighF, dailyHighC, dailyHighK;
double dailyLowF;
int lowHour;
dailyHighF = getDailyHigh();
dailyLowF = getDailyLow();
lowHour = getLowHour();
dailyHighC = farh2cels(dailyHighF);
dailyHighK = cels2kelv(dailyHighC);
Another thing to note: your functions are declared to return double, but they declare, scanf, and return ints. Its not a huge problem as the integers will get automatically changed into doubles. But you will be much better off if you are consistent in your types. If the function will return a double, it should have a double variable inside it.
e.g.
double fahr2cels( double fahr );
...
double fahr = 101.0;
double celsius = fahr2cels( fahr );
the return statment in the function returns the value to the caller.
Related
I'm trying to learn C from the C Programming Language book, in there, one of the exercises is to make a Fahrenheit to Celsius converter.
my code following the books style and instructions is:
#include <stdio.h>
int main() {
float fhr;
for (fhr = 0; fhr <= 300; fhr += 20)
printf("%3.1f %6.1f\n", fhr, (5.0/9.0)*(fhr-32));
}
It says in the book:
I just want to know if making a celsius variable and then calling it in the printf function as an argument is better or doing it this way is better, from both human readability and more importantly if it makes any difference to the compiler (I.e. makes the program run any faster or slower.)
Thanks.
Making a variable and then passing it to the printf would surely improve the readability.
From the compiler point of view there's no actual difference. It doesn't affect runtime performances in any way. This is especially true when it comes down to the internal optimizations the compiler carries out.
From a compiler standpoint it potentially does have an impact. Depending on the compiler, it might see that the variable is only used once and "inline" the value anyway. Many may not, which would cause a hit to the overall performance. That being said, the performance hit would be inconsequential.
As for readability, storing it as its own variable would be easier to look at, and maintain later. Although for a small program like this, the difference is also pretty inconsequential; however, it might start making a difference in larger programs, especially if the value is going to be used more than once.
#include <stdio.h>
int main()
{
float fhr;
for (fhr = 0; fhr <= 300; fhr += 20)
{
float celsius = (5.0/9.0)*(fhr-32);
printf("%3.1f %6.1f\n", fhr, celsius);
}
}
You might also want to consider using a function, to abstract out how this value is determined. Again, this does create a hit to performance, and isn't necessary for such a small program, but would provide access to a way to determine the value from more places in the program. This would mean you would not need to rely on passing the value around, or having the variable within scope:
float fahrenheit_to_celsius(float fhr)
{
return 5.0 / 9.0 * (fhr - 32)
}
int main()
{
float fhr;
for (fhr = 0; fhr <= 300; fhr += 20)
{
float celsius = fahrenheit_to_celsius(fhr);
printf("%3.1f %6.1f\n", fhr, celsius);
}
}
You can also use a function for it, it won't be slower, and it's way better for readability (in my opinion)!
#include <stdio.h>
double fhr_to_cls(double fhr)
{
return ((5.0 / 9.0) * ( fhr - 32));
}
int main()
{
double fhr;
for (fhr = 0; fhr <= 300; fhr += 20)
printf("%3.1f %6.1f\n", fhr, fhr_to_cls(fhr));
}
regarding:
for (fhr = 0; fhr <= 300; fhr += 20)
printf("%3.1f %6.1f\n", fhr, (5.0/9.0)*(fhr-32));
the 0 and 300 and 20 and 32 are all integers that the code is trying to stuff into a float
the 5.0and9/0aredoubles`
to correct all the above, Suggest:
for ( fhr = 0.0f; fhr <= 300.0f; fhr += 20.0f )
printf("%3.1f %6.1f\n", fhr, (5.0f / 9.0f )*(fhr-32.0f));
I run a loop a million times. Within the loop I call a C function to do some math (generating random variables from various distributions, to be exact). As part of that function, I declare a couple of double variables to hold parts of the transformation. An example:
void getRandNorm(double *randnorm, double mean, double var, int n)
{
// Declare variables
double u1;
double u2;
int arrptr = 0;
double sigma = sqrt(var); // the standard deviation
while (arrptr < n) {
// Generate two uniform random variables
u1 = rand() / (double)RAND_MAX;
u2 = rand() / (double)RAND_MAX;
// Box-Muller transform
randnorm[arrptr] = sqrt(-2*log(u1))*cos(2*pi*u2)*sigma+mean;
arrptr++;
if (arrptr < n) { // for an odd n, we cannot add off the end
randnorm[arrptr] = sqrt(-2*log(u2))*cos(2*pi*u1)*sigma+mean;
arrptr++;
}
}
}
And the calling loop:
iter = 1000000 // or something
for (i = 0; i < iter; i++) {
// lots of if statements
getRandNorm(sample1, truemean1, truevar1, n);
// some more analysis
}
I am working on speeding up the runtime. It occurs to me that I don't know what is happening with all these double variables that I am declaring. I assume a new 8 byte chunk of memory is allocated for the double for each of the one million loops. What happens to all those memory locations? They are declared within a C function; do they survive that function? Are they still locked up until the script exits?
The context for this question is wrapping this C program into a python function. If I'm going to execute this function multiple times in parallel from python, I want to be sure that I'm being as thrifty with memory usage as possible.
If you're talking about something like this:
for(int i=0;i<100000;i++){
double d = 5;
// some other stuff here
}
d is only allocated once by the compiler. It's mostly equivalent to declaring it above the for loop, except that the scope doesn't extend as far.
However, if you are doing something like this:
for(int i=0;i<1000000;i++){
double *d = malloc(sizeof(double));
free(d);
}
Then yes, you will allocate a double 1 million times, but it will likely re-use the memory for subsequent allocations. Finally, if you don't free the memory in my second example, you'll leak 16-32MB of memory.
The short answer is: NO, it should not matter if you declare these double variables inside the loop in C. By double variable, I assume you mean variables of type double.
The long answer is: Please post your code so people can tell you if you do something wrong and how to fix it to improve correctness and/or performance (a vast subject).
The final answer is: with the code provided, it makes no difference whether you declare u1 and u2 inside the body of the loop or outside. A good compiler will likely generate the same code.
You can improve the code a tiny bit by testing the odd case just once:
void getRandNorm(double *randnorm, double mean, double var, int n, double pi) {
// Declare variables
double u1, u2;
double sigma = sqrt(var); // the standard deviation
int arrptr, odd;
odd = n & 1; // check if n is odd
n -= odd; // make n even
for (arrptr = 0; arrptr < n; arrptr += 2) {
// Generate two uniform random variables
u1 = rand() / (double)RAND_MAX;
u2 = rand() / (double)RAND_MAX;
// Box-Muller transform
randnorm[arrptr + 0] = sqrt(-2*log(u1)) * cos(2*pi*u2) * sigma + mean;
randnorm[arrptr + 1] = sqrt(-2*log(u2)) * cos(2*pi*u1) * sigma + mean;
}
if (odd) {
u1 = rand() / (double)RAND_MAX;
u2 = rand() / (double)RAND_MAX;
randnorm[arrptr++] = sqrt(-2*log(u1)) * cos(2*pi*u2) * sigma + mean;
}
}
Note: arrptr + 0 is here for symmetry, the compiler will not generate any code for this addition.
regarding your question: If I run a loop a million times, do I have to worry about declaring doubles in each iteration?
The variables are being declared on the stack. So they 'disappear' when the function exits. The next execution of the function 're-creates' the variables, so (in reality) there is only a single instance of the variables and even then, only while the function is being executed.
So it does not matter how many times you call the function.
I'm trying to figure out this issue but I can't find any answer regarding the C language. The issue is that when I try to use the return value in another function, that value isn't coming through and it's coming out as '0' when printed.
int getFinanceAmt(float Cost, float Deposit){
float Financing;
Financing = Cost - Deposit;
printf("%f\n", Financing);
return Financing;}
So the goal is to utilize that return value and plug in into an equation inside of this function:
int getInterest(float Financing, float interestRate){
float interest;
interest = Financing * interestRate;
printf("%f\n", interest);
return interest;}
I have to do this in another function as well which is where 'interestRate' came from. That is also in another function. Is it right that I need some sort of pointer?
You have a return type mismatch. change your return types to float and it should run fine
First, in getFinanceAmt it looks like the function is declared to return an int, but later is returning a float. So first update getFinanceAmt to:
float getFinanceAmt(float cost, float deposit)
{
float financing;
financing = cost - deposit;
printf("%f\n", financing);
return financing;
}
Same thing is going on in the other function. But more importantly, you need to actually call the first function by name, and give it the needed parameters that we declared above. I would recommend just taking in three parameters in getInterest, then using them internally to call getFinanceAmt.
float getInterest(float cost, float deposit, float interestRate)
{
float interest;
interest = getFinanceAmt(cost, deposit) * interestRate;
printf("%f\n", interest);
return interest;
}
Fixing the issue with the wrong return type for the two funtions, you could do something like this to use the value returned from one as the argument for the other:
float getFinanceAmt(float Cost, float Deposit)
{
return Cost - Deposit;
}
float getInterest(float Financing, float interestRate)
{
return Financing * interestRate;
}
void foo()
{
float cost, deposit, rate;
/* more code here, which initializes the above variables */
printf("Interest is %f\n", getInterest(getFinanceAmt(cost, deposit), rate));
}
No, as I see, you don't need a pointer here. In your case, there's mismatch in your intention and your code.
Financing and interest are of type float but the function returning them are having the return type as int. You may want to change the function return types to float to make them compatible.
Cannot figure out what is wrong with the formula for the monthlyPayment, I am brand new to programming and so far I have spent 6 hours on this program.
void calcStuff(float loan, float rate, int years, float* monthlyPayment,
float* interestEarned)
{
//Define Variables
float ratePer;
int numPer;
float a;
float b;
float powf( float a , float b );
//Calculate the rate per period and number of periods
ratePer = ( rate / 100 ) / 12;
numPer = years * 12;
a = ( 1 + ratePer );
b = ( -numPer );
//Calculate the monthly payments and the interest earned
*monthlyPayment = (( ratePer * loan ) / ( 1 - powf ));
*interestEarned = (( *monthlyPayment * numPer )-loan );
return;
}
I also cannot seem to format it correctly
You error probably comes from the powf, as mentionned in my comment. You can remove the declaration, it is not needed.
Also your a and b variables are never used. If you intended to divide by (1 - a^b) for your monthlyPayment formula, you can do it by using the actual powf() function, declared in math.h :
#include<math.h>
// your code
*monthlyPayment = (( ratePer * loan ) / ( 1 - powf(a, b) ));
Oh, and don't forget to link with -lm to use the libmath ;)
Not that its wrong, but why use pointer arguments here?
void calcStuff(float loan, float rate, int years, float* monthlyPayment,
float* interestEarned)
Now, here:
//Define Variables
float ratePer;
int numPer;
float a;
float b;
float powf( float a , float b );
You are NOT DEFINING variables! You are DECLARING variables and you are also declaring a function. This difference is important in C. As far as variables are concern, this means that you're only declaring a name but you don't initialise memory with some value. In the case of the function it means that you're only declaring the signature of the function without actually defining what it should do. In C, too, you can't define a function within another function so declaring one with float powf( float a , float b ) is an error and I'd expect your compiler to complain.
*monthlyPayment = (( ratePer * loan ) / ( 1 - powf ));
( 1 - powf ) is an error of course. If you needed to call a function with powf's signature you should do it like this powf(aFloat, anotherFloat). But as already mentioned there is no DEFINITION for such a function in your program, just a declaration and in a place where it shouldn't be. When parsed by your compiler, however, powf will probably trigger a "variable not declared" error of some sort since it looks like a variable which is not declared/defined anywhere in your code.
return;
Finally, there's no need to return anything.. your function is void.
I'm trying to integrate the function 1/((1+x^2)x^0.5) between 0 and infinity using the trapezium rule.
I need to find the value of N that gives the highest precision possible when using a double float, which I have done by running the program with increasing values of N until there is no difference between the totals given by consecutive values of N. However I am stuck in an infinite loop.
Thanks
Beth
#include<stdio.h>
#include<math.h>
#include<float.h>
double inter(double x, double h, double y, double N, double total)
{
h=(y-x)/(N-1);
total= total +0.5*(1/((1+pow(x,2))*sqrt(x)));
x=x+h;
while (x<y)
{
total=total+(1/((1+pow(x,2))*sqrt(x)));
x=x+h;
//printf("t - %lf \n", total);
//printf("x - %lf \n", x);
}
total= total +0.5*(1/((1+pow(x,2))*sqrt(x)));
total=total*h;
return total;
}
main()
{
double x,y,total,h,c,d,f,N, finish;
x=DBL_EPSILON;
y=331;
total=0;
N=0.5;
c=inter(x,h,y,N,total);
d=0;
finish=0;
while(finish==0)
{
d=inter(x,h,y,N,total);
if(d==c)
{
finish=1;
}
else
{
c=d;
d=0;
h++;
printf("%lf/n", h);
}
}
printf("%lf\n", d);
}
In your iter() function, h is negative, which causes x to go negative. sqrt() of a negative number returns NaN. Additionally, because h is negative, x continues to get smaller, thus is always being smaller than y, which is the cause of the infinite loop.
h is negative because the denominator (N-1) comes out to -0.5 (N is passed in as 0.5).
double h has not been initialised. You are passing it as a function argument, which then overwrites it to use as a local variable. However, in the main loop you increment h (using the ++ operator which would be better as h+=1) and then pass it to the function again, but it has no effect, as h is still over written in the function.
As a point of technique, you are using double finish as a boolean. It should be int finish.