I am trying to create a conversion table using the C programing language. I want to convert the temperature from -250 °F to 250 °C increments of 10. However, I am not getting the Celsius output:
#include <p18f458.h>
#include <stdio.h>
#pragma config WDT = OFF
#define LOWER -250 /* lower limit of table */
#define UPPER 250 /* upper limit */
#define STEP 10 /* step size */
void main(void)
{
int fh, cel;
cel = (fh - 32) * 5 / 9;
for (fh = LOWER; fh <= UPPER; fh = fh + STEP)
printf("%d \t %6.1f\n", fh, cel);
while(1);
}
Fahrenheit Celsius
-250
-240
-230
-220
-210
-200
-190
-180
-170
-160
-150
-140
-130
-120
-110 .......
The code runs on a PIC18F458 microcontroller.
Recalculate each time
Use floating point math
// dddd123456789012ffffff
puts(" Fahrenheit Celsius");
// cel = (fh - 32) * 5 / 9;
for (fh = LOWER; fh <= UPPER; fh = fh + STEP) {
double cel = (fh - 32.0) * 5.0 / 9.0;
printf(" %4d %6.1f\n", fh, cel);
}
If wanting to avoid floating point types and math, use a scaled integer math to calculate decidegrees to achieve "%6.1f" like output. Scale temperature by 10. Integer division truncates the fraction, so add a signed offset of 5 to form a rounded result.
int offset = (fh - 32) > 0 : 5 : -5;
int deci_celcuis = ((fh - 32) * 10 * 5 + offset) / 9;
Printing is a little tricky. Various approaches exist.
int whole = deci_celcuis/10;
int frac = deci_celcuis%10;
char *sign = (whole < 0 || frac < 0) ? "-", "";
printf(" %4d %s%d.%d\n", fh, sign, abs(whole), abs(frac));
As others have noted: 1) use floating point to avoid integer division and truncation errors, 2) recalculate values inside the loop.
It would be a shame to miss this opportunity to produce parallel tables of F->C and also C->F for the given range.
#define LOWER -250
#define UPPER 250
#define STEP 10
int main() {
puts( " F C C F" );
for( int i = UPPER; i >= LOWER; i -= STEP ) {
printf( "%6.0f %6.0f", (double)i, (i - 32.0) * 5.0 / 9.0 );
printf( " " );
printf( "%6.0f %6.0f\n", (double)i, i * 9.0 / 5.0 + 32.0 );
}
return 0;
}
F C C F
250 121 250 482
240 116 240 464
230 110 230 446
220 104 220 428
210 99 210 410
200 93 200 392
// omitted...
-220 -140 -220 -364
-230 -146 -230 -382
-240 -151 -240 -400
-250 -157 -250 -418
Ordinary mercury thermometers condition people to expect warmer temperatures at the top, and cooler temperatures 'below'... This table reverses the sequence presented in the OP to conform to people's expectations.
cel = (fh - 32) * 5 / 9;
This statement is outside the loop, hence it will only ever print once.
. Add it in the loop and your code would work as expected.
Related
Im learning from start C basic.And i dont understand character wide.When i change it nothing visual happens,so i dont know what is purpose of this
I was researching and at first i discovered that its not string length but
character datatype,but more info i wasnt able to find
main()
{
float farh, celsium ;
int lower, upper, step;
lower = 0;
upper = 300;
step = 20;
farh = lower;
while(farh <= upper) {
celsium = (5.0/9.0) * (farh - 32.0);
printf( "%5.2f %5.2f\n",farh, celsium);
farh = farh + step;
}
}
output is temperature in celsuim and fahrenheit (0.000000 -17.777779)
in the code above
%5.2f
represent each argument to be alerted with character wide at least 5 and with 2 numbers after decimal point. But what changes if i write 2, 6 or other number instead of 5?
printf("%5.2f\n", 3.223467856);
Consider the above statement:
printing with %5.2f will generate : _3.22 ( the symbol _ represents a blank space at the beginning, won't be printed in console)
5: The number will occupy space of 5 character wide. (.) dot occupies 1 char space too)
2: The number will occupy 2 digits after decimal point(.)
printf("%6.2f\n", 3.223467856);
printing with %6.2f will generate : __3.22
printf("%6.3f\n", 3.223467856);
printing with %6.2f will generate : _3.223
If you modify the program (with some cleanup):
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int const lower_limit = 0;
int const upper_limit = 300;
int const step = 20;
float fahrenheit = lower_limit;
while (fahrenheit <= upper_limit) {
float const celsius = (5.0f / 9.0f) * (fahrenheit - 32.0f);
printf("%9.6f\t%10.6f\n", fahrenheit, celsius);
fahrenheit += step;
}
return EXIT_SUCCESS;
}
You'll see the difference between %9.6f and %10.6f which should show something like:
0.000000 -17.777779
20.000000 -6.666667
40.000000 4.444445
60.000000 15.555556
80.000000 26.666668
100.000000 37.777779
120.000000 48.888893
140.000000 60.000004
160.000000 71.111115
180.000000 82.222229
200.000000 93.333336
220.000000 104.444450
240.000000 115.555557
260.000000 126.666672
280.000000 137.777786
300.000000 148.888901
You see a difference in behaviour when fahrenheit goes from 0 to 20 vs from 80 to 100.
I have attempted to implement the sine function in C, yet I am getting weird results. Here are the three functions I am using to calculate sine:
#define PI 3.14159265358979323846
#define DEPTH 16
double sine(long double);
long double pow(long double, unsigned int);
unsigned int fact(unsigned int);
double sine(long double x) {
long double i_x = x *= PI/180;
int n = 3, d = 0, sign = -1;
// fails past 67 degrees
for (; d < DEPTH; n += 2, d++, sign *= -1) {
x += pow(i_x, n) / fact(n) * sign;
}
return x;
}
long double pow(long double base, unsigned int exp) {
double answer = 1;
while (exp) {
answer *= base;
exp--;
}
return answer;
}
unsigned int fact(unsigned int n) {
unsigned int answer = 1;
while (n > 1) {
answer *= n--;
}
return answer;
}
To test it I have been testing it against the built in sine function as follows:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
main() {
for (int i = 0; i <= 180; i++) {
printf("sin(%i) = %lf, %lf\n", i, sine(i), sin(i*3.14159265358979323846/180));
}
exit(EXIT_SUCCESS);
}
Up through 67 degrees, it calculates the same as the built in function. Though, as it increases past 67 it typically strays gets further and further from the actual value.
Here is an example output:
>> sin(100) = 0.987711, 0.984808
>> sin(101) = 0.986885, 0.981627
>> sin(102) = 0.987056, 0.978148
>> sin(103) = 0.988830, 0.974370
>> sin(104) = 0.993060, 0.970296
>> sin(105) = 1.000948, 0.965926
>> sin(106) = 1.014169, 0.961262
>> sin(107) = 1.035052, 0.956305
>> sin(108) = 1.066807, 0.951057
>> sin(109) = 1.113846, 0.945519
>> sin(110) = 1.182194, 0.939693
>> sin(111) = 1.280047, 0.933580
>> sin(112) = 1.418502, 0.927184
>> sin(113) = 1.612527, 0.920505
>> sin(114) = 1.882224, 0.913545
>> sin(115) = 2.254492, 0.906308
>> sin(116) = 2.765192, 0.898794
>> sin(117) = 3.461969, 0.891007
...
>> sin(180) = 8431648.192239, 0.000000
Does anybody know why this is happening? I am using Visual Studio 2017 on Windows 7, if that provides any useful information.
Each time your for loop progresses, n is increased by 2 and hence for DEPTH = 16, near the end of loop you have to calculate factorials of numbers as big as 30 and you are using unsigned int that can only store values as big as 2^32 = 4294967296 ~= 12! and this causes overflow in your factorial function which in turn gives you the wrong factorial.
Even if you used long double for it and I already stated in my comments that long double in MSCRT is mapped to double (Reference) you'd still see some anomalies probably at larger angles because although double can store values as big as 1.8E+308 but it loses its granularity at 2^53 = 9007199254740992 ~= 18! (i.e. 2^53 + 1 stored as a double is equal to 2^53). So once you go up in angles, the effect of this behavior becomes larger and larger to the point that it is noticeable in the 6 decimal precision that you are using with printf().
Although you are on the right track, you should use a bignum library like GMP or libcrypto. They can perform these calculations without the loss of precision.
BTW, since your are developing on Windows 7 that means you are either using x86 or x86-64. On these platforms, x87 is capable of performing extended precision (as per 754 standard) operations with 80 bits but I am unaware of compiler intrinsics that can give you that capability without resorting to assembly code.
I also would like to direct your attention to range reduction techniques. Although I still recommend using bignum libs, if you are good between 0 and 90 degrees (0 and 45 if I'm to be more strict), you can compute the sine() of all other angles just by simple trigonometric identities.
UPDATE:
Actually I'm gonna correct myself about using doubles in factorial calculations. After writing a simple program I verified that when I usedouble to store factorials, they are correct even if I go upper than 18. After giving it some thought I realized that in the case of factorials, the situation with double's granularity is a little bit more complex. I'll give you an example to make it clear:
19! = 19 * 18 * ... * 2 * 1
in this number 18, 16, 14, ... , 2 are all multiples of 2 and since a multiplication by 2 is equivalent to a shift to the left in binary representation, all lower bits in 19! are already 0 and hence when double's rounding kicks in for integers greater than 2^53, these factorials are unaffected. You can compute the number of least significant zeroes in the binary representation of 19! by counting the number of 2's which is 16. (for 20!, it is 18)
I'm gonna go up to 1.8e+308 and check if all the factorials are unaffected or not. I'll update you with the results.
UPDATE 2:
If we use doubles to hold factorials, they are affected by rounding from 23! onward. It can be easily shown, because 2^74 < 23! < 2^75 which means that at least 75 bits of precision is required to represent it, but since 23! has 19 least significant bits with the value of 0, so it needs 75 - 19 = 56 which is larger than 53 bits provided by double.
For 22!, it is 51 bits (you can calculate it yourself).
There are multiple issues in your code:
You redefine the standard function pow() with a different prototype. This may cause problems when you link the program as en executable. Use a different anme such as pow_int.
You should define the pow_int and fact functions as static before the sine function. It may allow for better optimisation at compile time.
Indeed fact is limited by the range of type unsigned int which is much less than the precision of type long double. Factorials beyond 12 have an incorrect value, causing a loss of precision.
You could actually compute the terms incrementally, saving a lot of computations and avoiding potential loss of precision.
The prototype for main() without arguments is int main(void)
The computation of PI/180 is performed as double, which is less precise than long double. You should write the expression as x = x * PI / 180;
DEPTH should be increased to improve the precision. At least 4 more terms bring a substantial improvement.
You should apply a range reduction: taking advantage of the sine function symmetric and periodic nature, computation can be performed with fewer terms on x modulo 90 or even 45 degrees.
Here is a modified version:
#include <stdio.h>
#include <math.h>
#define PI_L 3.14159265358979323846264338327950288L
#define PI 3.14159265358979323846264338327950288
#define DEPTH 24
double sine(long double x) {
long double res, term, x2, t1;
int phase;
x = remquol(x, 90, &phase);
if (phase & 1)
x = 90 - x;
x = x * PI_L / 180; // convert x to radians
x2 = x * x; // pre-compute x^2
// compute the sine series: x - x^3/3! + x^5/5! ...
res = term = x; // the first term is x
for (int n = 1; n < DEPTH; n += 4) {
// to reduce precision loss, compute 2 terms for each iteration
t1 = term * x2 / ((n + 1) * (n + 2));
term = t1 * x2 / ((n + 3) * (n + 4));
// update the result with the difference of the terms
res += term - t1;
}
if (phase & 2)
res = -res;
return (double)res;
}
int main(void) {
printf("deg sin sine delta\n\n");
for (int i = 0; i <= 360; i += 10) {
double s1 = sin(i * PI / 180);
double s2 = sine(i);
printf("%3i %20.17f %20.17f %g\n", i, s1, s2, s2 - s1);
}
return 0;
}
The output is:
deg sin sine delta
0 0.00000000000000000 0.00000000000000000 0
10 0.17364817766693033 0.17364817766693036 2.77556e-17
20 0.34202014332566871 0.34202014332566871 0
30 0.49999999999999994 0.50000000000000000 5.55112e-17
40 0.64278760968653925 0.64278760968653936 1.11022e-16
50 0.76604444311897801 0.76604444311897801 0
60 0.86602540378443860 0.86602540378443860 0
70 0.93969262078590832 0.93969262078590843 1.11022e-16
80 0.98480775301220802 0.98480775301220802 0
90 1.00000000000000000 1.00000000000000000 0
100 0.98480775301220802 0.98480775301220802 0
110 0.93969262078590843 0.93969262078590843 0
120 0.86602540378443882 0.86602540378443860 -2.22045e-16
130 0.76604444311897812 0.76604444311897801 -1.11022e-16
140 0.64278760968653947 0.64278760968653936 -1.11022e-16
150 0.49999999999999994 0.50000000000000000 5.55112e-17
160 0.34202014332566888 0.34202014332566871 -1.66533e-16
170 0.17364817766693025 0.17364817766693036 1.11022e-16
180 0.00000000000000012 -0.00000000000000000 -1.22465e-16
190 -0.17364817766693047 -0.17364817766693036 1.11022e-16
200 -0.34202014332566866 -0.34202014332566871 -5.55112e-17
210 -0.50000000000000011 -0.50000000000000000 1.11022e-16
220 -0.64278760968653925 -0.64278760968653936 -1.11022e-16
230 -0.76604444311897790 -0.76604444311897801 -1.11022e-16
240 -0.86602540378443837 -0.86602540378443860 -2.22045e-16
250 -0.93969262078590821 -0.93969262078590843 -2.22045e-16
260 -0.98480775301220802 -0.98480775301220802 0
270 -1.00000000000000000 -1.00000000000000000 0
280 -0.98480775301220813 -0.98480775301220802 1.11022e-16
290 -0.93969262078590854 -0.93969262078590843 1.11022e-16
300 -0.86602540378443860 -0.86602540378443860 0
310 -0.76604444311897812 -0.76604444311897801 1.11022e-16
320 -0.64278760968653958 -0.64278760968653936 2.22045e-16
330 -0.50000000000000044 -0.50000000000000000 4.44089e-16
340 -0.34202014332566855 -0.34202014332566871 -1.66533e-16
350 -0.17364817766693127 -0.17364817766693036 9.15934e-16
360 -0.00000000000000024 0.00000000000000000 2.44929e-16
As can be seen above, the sine() function seems more precise than the standard sin function on my system: sin(180 * M_PI / 128) should be 0 precisely. Similarly, sin(150 * M_PI / 128) should be 0.5 exactly.
Your way of polynomial series evaluation is numerically unstable. Try horner's method which is more stable than power calculations.
Your problem is here:
for (; d < DEPTH; n += 2, d++, sign *= -1) {
x += pow(i_x, n) / fact(n) * sign;
}
You are using d < DEPTH in error when it should be n < DEPTH, d is irrelevant to your computations within the loop. The following should work -- although I have not compiled to test.
for (; n < DEPTH; n += 2, sign *= -1) {
x += pow(i_x, n) / fact(n) * sign;
}
note: a DEPTH of 12 (e.g. Taylor Series expansion with terms 1, 3, 5, ... 11) is sufficient for 3e-10 error -- 3 ten billionths at 60-degrees. (though error increases as angle increases between 0-360, a DEPTH of 20 will keep error less than 1.0e-8 over the entire range.)
Enabling compiler warnings would have caught the unused d in sine.
Here is an example of code with the changes (note: Gnu provides a constant M_PI for PI):
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#define DEPTH 16
/* n factorial */
uint64_t nfact (int n)
{
if (n <= 0) return 1;
uint64_t s = n;
while (--n)
s *= n;
return s;
}
/* y ^ x */
double powerd (const double y, const int x)
{
if (!x) return 1;
double r = y;
for (int i = 1; i < x; i++)
r *= y;
return r;
}
double sine (double deg)
{
double rad = deg * M_PI / 180.0,
x = rad;
int sign = -1;
for (int n = 3; n < DEPTH; n += 2, sign *= -1)
x += sign * powerd (rad, n) / nfact (n);
return x;
}
int main (void) {
printf (" deg sin sine\n\n");
for (int i = 0; i < 180; i++)
printf ("%3d %11.8f %11.8f\n", i, sin (i * M_PI / 180.0), sine (i));
return 0;
}
Example Use/Output
$ ./bin/sine
deg sin sine
0 0.00000000 0.00000000
1 0.01745241 0.01745241
2 0.03489950 0.03489950
3 0.05233596 0.05233596
4 0.06975647 0.06975647
5 0.08715574 0.08715574
6 0.10452846 0.10452846
7 0.12186934 0.12186934
8 0.13917310 0.13917310
9 0.15643447 0.15643447
10 0.17364818 0.17364818
11 0.19080900 0.19080900
12 0.20791169 0.20791169
13 0.22495105 0.22495105
14 0.24192190 0.24192190
15 0.25881905 0.25881905
16 0.27563736 0.27563736
17 0.29237170 0.29237170
18 0.30901699 0.30901699
19 0.32556815 0.32556815
20 0.34202014 0.34202014
21 0.35836795 0.35836795
22 0.37460659 0.37460659
23 0.39073113 0.39073113
24 0.40673664 0.40673664
25 0.42261826 0.42261826
26 0.43837115 0.43837115
27 0.45399050 0.45399050
28 0.46947156 0.46947156
29 0.48480962 0.48480962
30 0.50000000 0.50000000
31 0.51503807 0.51503807
32 0.52991926 0.52991926
33 0.54463904 0.54463904
34 0.55919290 0.55919290
35 0.57357644 0.57357644
36 0.58778525 0.58778525
37 0.60181502 0.60181502
38 0.61566148 0.61566148
39 0.62932039 0.62932039
40 0.64278761 0.64278761
41 0.65605903 0.65605903
42 0.66913061 0.66913061
43 0.68199836 0.68199836
44 0.69465837 0.69465837
45 0.70710678 0.70710678
46 0.71933980 0.71933980
47 0.73135370 0.73135370
48 0.74314483 0.74314483
49 0.75470958 0.75470958
50 0.76604444 0.76604444
51 0.77714596 0.77714596
52 0.78801075 0.78801075
53 0.79863551 0.79863551
54 0.80901699 0.80901699
55 0.81915204 0.81915204
56 0.82903757 0.82903757
57 0.83867057 0.83867057
58 0.84804810 0.84804810
59 0.85716730 0.85716730
60 0.86602540 0.86602540
61 0.87461971 0.87461971
62 0.88294759 0.88294759
63 0.89100652 0.89100652
64 0.89879405 0.89879405
65 0.90630779 0.90630779
66 0.91354546 0.91354546
67 0.92050485 0.92050485
68 0.92718385 0.92718385
69 0.93358043 0.93358043
70 0.93969262 0.93969262
71 0.94551858 0.94551858
72 0.95105652 0.95105652
73 0.95630476 0.95630476
74 0.96126170 0.96126170
75 0.96592583 0.96592583
76 0.97029573 0.97029573
77 0.97437006 0.97437006
78 0.97814760 0.97814760
79 0.98162718 0.98162718
80 0.98480775 0.98480775
81 0.98768834 0.98768834
82 0.99026807 0.99026807
83 0.99254615 0.99254615
84 0.99452190 0.99452190
85 0.99619470 0.99619470
86 0.99756405 0.99756405
87 0.99862953 0.99862953
88 0.99939083 0.99939083
89 0.99984770 0.99984770
90 1.00000000 1.00000000
91 0.99984770 0.99984770
92 0.99939083 0.99939083
93 0.99862953 0.99862953
94 0.99756405 0.99756405
95 0.99619470 0.99619470
96 0.99452190 0.99452190
97 0.99254615 0.99254615
98 0.99026807 0.99026807
99 0.98768834 0.98768834
100 0.98480775 0.98480775
101 0.98162718 0.98162718
102 0.97814760 0.97814760
103 0.97437006 0.97437006
104 0.97029573 0.97029573
105 0.96592583 0.96592583
106 0.96126170 0.96126170
107 0.95630476 0.95630476
108 0.95105652 0.95105652
109 0.94551858 0.94551858
110 0.93969262 0.93969262
111 0.93358043 0.93358043
112 0.92718385 0.92718385
113 0.92050485 0.92050485
114 0.91354546 0.91354546
115 0.90630779 0.90630779
116 0.89879405 0.89879405
117 0.89100652 0.89100652
118 0.88294759 0.88294759
119 0.87461971 0.87461971
120 0.86602540 0.86602540
121 0.85716730 0.85716730
122 0.84804810 0.84804810
123 0.83867057 0.83867057
124 0.82903757 0.82903757
125 0.81915204 0.81915204
126 0.80901699 0.80901699
127 0.79863551 0.79863551
128 0.78801075 0.78801075
129 0.77714596 0.77714596
130 0.76604444 0.76604444
131 0.75470958 0.75470958
132 0.74314483 0.74314482
133 0.73135370 0.73135370
134 0.71933980 0.71933980
135 0.70710678 0.70710678
136 0.69465837 0.69465836
137 0.68199836 0.68199835
138 0.66913061 0.66913060
139 0.65605903 0.65605902
140 0.64278761 0.64278760
141 0.62932039 0.62932038
142 0.61566148 0.61566146
143 0.60181502 0.60181501
144 0.58778525 0.58778523
145 0.57357644 0.57357642
146 0.55919290 0.55919288
147 0.54463904 0.54463901
148 0.52991926 0.52991924
149 0.51503807 0.51503804
150 0.50000000 0.49999996
151 0.48480962 0.48480958
152 0.46947156 0.46947152
153 0.45399050 0.45399045
154 0.43837115 0.43837109
155 0.42261826 0.42261820
156 0.40673664 0.40673657
157 0.39073113 0.39073105
158 0.37460659 0.37460651
159 0.35836795 0.35836786
160 0.34202014 0.34202004
161 0.32556815 0.32556804
162 0.30901699 0.30901686
163 0.29237170 0.29237156
164 0.27563736 0.27563720
165 0.25881905 0.25881887
166 0.24192190 0.24192170
167 0.22495105 0.22495084
168 0.20791169 0.20791145
169 0.19080900 0.19080873
170 0.17364818 0.17364788
171 0.15643447 0.15643414
172 0.13917310 0.13917274
173 0.12186934 0.12186895
174 0.10452846 0.10452803
175 0.08715574 0.08715526
176 0.06975647 0.06975595
177 0.05233596 0.05233537
178 0.03489950 0.03489886
179 0.01745241 0.01745170
Error Check based on DEPTH
In response to the comment regarding computing the error, you investigate the error associated with Taylor-Series expansions for both sin and cos base on the number of terms by varying DEPTH and setting an max error of EMAX 1.0e-8 using something similar to the following for the range of 0-360 (or 0-2PI),
#define DEPTH 20
#define EMAX 1.0e-8
...
/* sine as above */
...
/* cos with taylor series expansion to n = DEPTH */
long double cose (const long double deg)
{
long double rad = deg * M_PI / 180.0,
x = 1.0;
int sign = -1;
for (int n = 2; n < DEPTH; n += 2, sign *= -1)
x += sign * powerd (rad, n) / nfact (n);
return x;
}
int main (void) {
for (int i = 0; i < 180; i++) {
long double sinlibc = sin (i * M_PI / 180.0),
coslibc = cos (i * M_PI / 180.0),
sints = sine (i),
costs = cose (i),
serr = fabs (sinlibc - sints),
cerr = fabs (coslibc - costs);
if (serr > EMAX)
fprintf (stderr, "sine error exceeds limit of %e\n"
"%3d %11.8Lf %11.8Lf %Le\n",
EMAX, i, sinlibc, sints, serr);
if (cerr > EMAX)
fprintf (stderr, "cose error exceeds limit of %e\n"
"%3d %11.8Lf %11.8Lf %Le\n",
EMAX, i, coslibc, costs, cerr);
}
return 0;
}
If you check, you will find that for anything less than DEPTH 20 (10 terms in each expansion), error will exceed 1.0e-8 for higher angles. Surprisingly, the expansions are very accurate over the first quadrant for values of DEPTH as low as 12 (6-terms).
Addemdum - Improved Taylor-Series Accuracy Using 0-90 & Quadrants
In the normal Taylor-Series expansion, error grows as angle grows. And... because some just can't not tinker, I wanted to further compare accuracy between the libc sin/cos and the Taylor-Series if computations were limited to 0-90 degrees and the remainder of the period from 90-360 were handled by quadrant (2, 3 & 4) mirroring of results from 0-90. It works -- marvelously.
For example, the results of handing only angles 0-90 and bracketing angles between 90 - 180, 180 - 270 and 270 - 360 with an initial angle % 360 produces results comparable to the libc math lib functions. The maximum error between the libc and 8 & 10 term Taylor-Series expansions were, respectably:
Max Error from libc sin/cos
With TSLIM 16
sine_ts max err at : 90.00 deg -- 6.023182e-12
cose_ts max err at : 270.00 deg -- 6.513370e-11
With TSLIM 20
sine_ts max err at : 357.00 deg -- 5.342948e-16
cose_ts max err at : 270.00 deg -- 3.557149e-15
(with a large number of angles showing no difference at all)
The tweaked versions of sine and cose with Taylor-Series were as follows:
double sine (const double deg)
{
double fp = deg - (int64_t)deg, /* save fractional part of deg */
qdeg = (int64_t)deg % 360, /* get equivalent 0-359 deg angle */
rad, sine_deg; /* radians, sine_deg */
int pos_quad = 1, /* positive quadrant flag 1,2 */
sign = -1; /* taylor series term sign */
qdeg += fp; /* add fractional part back to angle */
/* get equivalent 0-90 degree angle, set pos_quad flag */
if (90 < qdeg && qdeg <= 180) /* in 2nd quadrant */
qdeg = 180 - qdeg;
else if (180 < qdeg && qdeg <= 270) { /* in 3rd quadrant */
qdeg = qdeg - 180;
pos_quad = 0;
}
else if (270 < qdeg && qdeg <= 360) { /* in 4th quadrant */
qdeg = 360 - qdeg;
pos_quad = 0;
}
rad = qdeg * M_PI / 180.0; /* convert to radians */
sine_deg = rad; /* save copy for computation */
/* compute Taylor-Series expansion for sine for TSLIM / 2 terms */
for (int n = 3; n < TSLIM; n += 2, sign *= -1) {
double p = rad;
uint64_t f = n;
for (int i = 1; i < n; i++) /* pow */
p *= rad;
for (int i = 1; i < n; i++) /* nfact */
f *= i;
sine_deg += sign * p / f; /* Taylor-series term */
}
return pos_quad ? sine_deg : -sine_deg;
}
and for cos
double cose (const double deg)
{
double fp = deg - (int64_t)deg, /* save fractional part of deg */
qdeg = (int64_t)deg % 360, /* get equivalent 0-359 deg angle */
rad, cose_deg = 1.0; /* radians, cose_deg */
int pos_quad = 1, /* positive quadrant flag 1,4 */
sign = -1; /* taylor series term sign */
qdeg += fp; /* add fractional part back to angle */
/* get equivalent 0-90 degree angle, set pos_quad flag */
if (90 < qdeg && qdeg <= 180) { /* in 2nd quadrant */
qdeg = 180 - qdeg;
pos_quad = 0;
}
else if (180 < qdeg && qdeg <= 270) { /* in 3rd quadrant */
qdeg = qdeg - 180;
pos_quad = 0;
}
else if (270 < qdeg && qdeg <= 360) /* in 4th quadrant */
qdeg = 360 - qdeg;
rad = qdeg * M_PI / 180.0; /* convert to radians */
/* compute Taylor-Series expansion for sine for TSLIM / 2 terms */
for (int n = 2; n < TSLIM; n += 2, sign *= -1) {
double p = rad;
uint64_t f = n;
for (int i = 1; i < n; i++) /* pow */
p *= rad;
for (int i = 1; i < n; i++) /* nfact */
f *= i;
cose_deg += sign * p / f; /* Taylor-series term */
}
return pos_quad ? cose_deg : -cose_deg;
}
Rabbit-trail end found...
Changing the angle range in main to -90 to 90 will still cover the whole sine range. but as the Taylor serie is starting from zero the DEPTH value can be reduced to 7. As earlier mentioned, making the fact function 64 bits unsigned
will fix the 67 degree problem.
I am having some trouble with the output of my program and can't figure out where I am going wrong. The Temperatures seem to be converting from celsius to Fahrenheit correctly, but when it comes to the the wind chill and heat index values, they are incorrect. This makes me think that something is wrong with the way I'm calculating them in my functions? If I could get an explanation to where my logic is wrong that would be great. Thanks in advance and sorry for my poor formatting!
#include <stdio.h>
#include <math.h>
#define L_Limit -20
#define U_Limit 50
#define c1 -42.379
#define c2 2.04901523
#define c3 10.14333127
#define c4 -0.22475541
#define c5 -6.83783E-3
#define c6 -5.481717E-2
#define c7 1.22874E-3
#define c8 8.5282E-4
#define c9 -1.99E-6
#define d1 35.74
#define d2 0.6125
#define d3 35.75
#define d4 0.4275
double compute_heat_index(int num1, int num2);
double compute_wind_chill(int num1, int num2);
double compute_heat_index(int num1, int num2)
{
int celsius;
double humid=.40;
double celsius_f=0, heat_index=0;
int ext1=0;
for(celsius=1;celsius<=num2;celsius++)
{
printf("%d\t", celsius);
celsius_f=(celsius*(9/5))+32;
printf("%2.2lf\t", celsius_f);
for(humid=.40;humid<=1;humid=humid+.10)
{
heat_index=c1+(c2*celsius_f)+(c3*humid)+. (c4*humid*celsius_f)+(c5*pow(celsius,2))+(c6*pow(humid,2))+(c7*pow(celsius,2)*humid)+(c8*celsius*pow(humid,2))+(c9*pow(celsius,2)*pow(humid,2));
if(heat_index<80)
printf("x\t");
else
printf("%2.2lf/t", heat_index);
}
if(celsius_f>100)
{
ext1++;
}
humid=.40;
celsius_f=0;
heat_index=0;
}
return heat_index;
}
double compute_wind_chill(int num1, int num2)
{
int celsius, wind=5;
double celsius_f=0, wind_chill=0;
int ext2=0;
for(celsius=1;celsius<=num2;celsius++)
{
printf("%d\t", celsius);
celsius_f=(celsius*(9/5))+32;
printf("%lf\t", celsius_f);
for(wind=5;wind<=40;wind=wind+5)
{
wind_chill=d1+(d2*celsius_f)-(d3*wind)+(d4*celsius_f*wind);
if(wind_chill>50)
printf("x\t");
else
printf("%lf\t", wind_chill);
}
if(celsius_f<-20)
{
ext2++;
}
wind=5;
celsius_f=0;
wind_chill=0;
}
return wind_chill;
}
int main(void)
{
double num1, num2;
int ext1=0, ext2=0;
printf("Input a range of values using two numbers:\n");
scanf("\n%lf%lf", &num1, &num2);
while(num1<L_Limit&&num1>U_Limit&&num2<L_Limit&&num2<U_Limit)
{
printf("Range of Values are Invalid!\n");
scanf("\n%lf%lf", &num1, &num2);
}
printf("Celsius\tFahrenheit\t5mph\t10mph\t15mph\t20mph\t25mph\t30mph\t35mph\t40mph\n");
compute_wind_chill(num1, num2);
printf("\nTotal Extreme Values: %d", ext1);
compute_heat_index(num1, num2);
printf("\nTotal Extreme Values: %d", ext2);
return 0;
}
While I make no comment on the correctness of your stoichiometric calculations (though I provide links and hints at the end), the following will help you find the problem, not only here, but hopefully in all future code you write as well. You are making things harder on yourself than they need be just by how you are formatting your code. Unless you are competing in a contest to see how few lines you can use, then for goodness sake, make things easier on yourself by 'opening up' you code a bit. This will make it much easier for you, and anyone helping you, to follow the logic of your code and find logic errors. For example, it is almost impossible to spot logic errors in:
heat_index=c1+(c2*celsius_f)+(c3*humid)+. (c4*humid*celsius_f)+(c5*pow(celsius,2))+(c6*pow(humid,2))+(c7*pow(celsius,2)*humid)+(c8*celsius*pow(humid,2))+(c9*pow(celsius,2)*pow(humid,2));
(of course your compiler will loudly complain about the errouneous '.' at the end of the first line)
It is much more readable written as:
heat_index = c1 + (c2 * celsius_f) + (c3 * humid) +
(c4 * humid * celsius_f) + (c5 * pow (celsius, 2)) +
(c6 * pow (humid, 2)) + (c7 * pow (celsius, 2) * humid) +
(c8 * celsius * pow (humid, 2)) +
(c9 * pow (celsius, 2) * pow (humid, 2));
or even:
heat_index = c1 +
(c2 * celsius_f) +
(c3 * humid) +
(c4 * humid * celsius_f) +
(c5 * pow (celsius, 2)) +
(c6 * pow (humid, 2)) +
(c7 * pow (celsius, 2) * humid) +
(c8 * celsius * pow (humid, 2)) +
(c9 * pow (celsius, 2) * pow (humid, 2));
NOTE: above you can easily see the misuse of celsius where celsius_f (Fahrenheit) should be used. Also note there is no need for pow (celsius_f, 2) where celsius_f * celsius_f will do the job.
Do the same for your output. Make it easy for you to read so it will be easier for others to read as well.
(I'm getting old and maybe your young-eyes have no trouble with code without spaces, it is much easier on me to help you if your code is adequately spaced and properly indented and your output looks like something other than spaghetti strung across the screen)
Avoid using 'magic numbers' in your code, e.g.
for(wind=5;wind<=40;wind=wind+5)
If you need constants in your code, declare them as required. That way, there is only one place you need to change the value, easily found at the top, instead of picking though your code to find them. You have declared a large number for your wet-bulb/dry-blub calculations, a few more for your limits is all that is required, e.g.
#define HMIN .40 /* define needed constants */
#define HMAX 1.0 /* avoid putting 'magic' */
#define HSTEP 0.1 /* numbers in your code */
#define WMIN 5
#define WMAX 40
#define WSTEP 5
...
for (wind = WMIN; wind <= WMAX; wind = wind + WSTEP)
Note: your HMIN, HMAX, HSTEP values will change when you correct your units (see last paragraph).
It appears you are wanting to return the values of ext1 and ext2 from your compute_wind_chill and compute_heat_index functions. If so, then your function type should match your return type needed. If you are wanting to indicate whether a extreme value was encountered by returning ext1 and ext2, then you should change your function type to int and assign the return to ext1 and ext2 in main, e.g.
int compute_heat_index (int num1, int num2);
int compute_wind_chill (int num1, int num2);
...
ext1 = compute_wind_chill (num1, num2);
printf ("\nTotal Extreme Values: %d\n", ext1);
...
ext2 = compute_heat_index (num1, num2);
printf ("\nTotal Extreme Values: %d\n", ext2);
Next, there is no need to make multiple calls to, e.g. printf when one will do. For example:
printf("%d\t", celsius);
celsius_f=(celsius*(9/5))+32;
printf("%2.2lf\t", celsius_f);
can be easily replaced with a single printf call just by logically ordering your celsius_f calculation, e.g.
celsius_f = (celsius * (9 / 5)) + 32;
printf ("%d\t% .2lf\t", celsius, celsius_f);
Why you declare num1 and num2 as double in main is a complete mystery. You pass them as int to your functions (where I assume num1 is supposed to be the lower loop value for temp in the functions instead of the hardcoded 1 you have). While you are free to allow users to enter e.g. 45.3 and read it as a double, and pass it as an int, it doesn't really make much logical sense. Here, the value of 45 is all that is ever used on your code. If you are reading as a double just to prevent error if a user enters 45.3, then that is a legitimate reason, but why a user would rather enter 45.3 instead of just 45 is another matter...
Your limit testing for values less/greater than L_Limit/U_Limit is a bit creative. It is better to simply put the values in ascending order to simplify the test, e.g.
/* VALIDATE all user input */
if (scanf ("%lf %lf", &num1, &num2) != 2) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
if (num1 > num2) { /* get values in ascending order */
double tmp = num1;
num1 = num2;
num2 = tmp;
}
while (num1 < L_Limit || num2 > U_Limit) { /* simple test */
Formatting your output is just something that takes a little more attention to detail. While I'm no fan of tab ('\t') formatting, I've made a quick attempt to clean things up a little to make the output more legible. Similarly, when you need an additional newline character, do not use the variadic printf ("\n");, there is no reason for the overhead just to output one character, use putchar ('\n'); instead. (note: you don't make that mistake, but I had to add a newline so it was worth mentioning here).
When you compile your code, always compile with warnings enabled, e.g. -Wall -Wextra in your compile string. You can add -pedantic for a few additional checks and there are a multitude of additional individual checks you can impose. Above all, do not accept code until it compiles cleanly, without warnings. Read the warnings you get. The compilers are quite good now at explaining exactly where the problem is and what you are doing wrong. (you can learn a lot of C, just by listening to what your compiler is telling you).
You can compile your code with something similar to the following:
$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -o bin/windchill windchill.c
Finally, putting it altogether, you could reformat your code and incorporate the changes above into something like the following that should make finding your stoichiometric logic error much easier. I have put my additional thoughts in the comments below:
#include <stdio.h>
#include <math.h>
#define L_Limit -20
#define U_Limit 50
#define c1 -42.379
#define c2 2.04901523
#define c3 10.14333127
#define c4 -0.22475541
#define c5 -6.83783E-3
#define c6 -5.481717E-2
#define c7 1.22874E-3
#define c8 8.5282E-4
#define c9 -1.99E-6
#define d1 35.74
#define d2 0.6125
#define d3 35.75
#define d4 0.4275
#define HMIN .40 /* define needed constants */
#define HMAX 1.0 /* avoid putting 'magic' */
#define HSTEP 0.1 /* number in your code */
#define WMIN 5
#define WMAX 40
#define WSTEP 5
/* you only need prototypes if you do not define your functions
* until AFTER the code that makes use of them. Moving the
* definitions AFTER main() makes the prototypes make sense,
* otherwise, just omit them...
*/
int compute_heat_index (int num1, int num2);
int compute_wind_chill (int num1, int num2);
int main (void) {
double num1 = L_Limit - 1.0, /* num1 & num2 should be int */
num2 = U_Limit + 1.0;
int ext1 = 0, ext2 = 0;
printf ("Input a range of temps in deg. C, (e.g. t1 t2): ");
/* VALIDATE all user input */
if (scanf ("%lf %lf", &num1, &num2) != 2) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
if (num1 > num2) { /* get values in ascending order */
double tmp = num1;
num1 = num2;
num2 = tmp;
}
while (num1 < L_Limit || num2 > U_Limit) { /* simple test */
fprintf (stderr, "error: values must be between %d - %d.\n",
L_Limit, U_Limit);
printf ("Input a range of temps in deg. C, (e.g. t1 t2): ");
if (scanf ("%lf %lf", &num1, &num2) != 2) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
}
/* make the output format easy to read */
printf ("\nDeg. C\t Deg. F\t 5mph\t 10mph\t 15mph\t"
" 20mph\t 25mph\t 30mph\t 35mph\t 40mph\n");
ext1 = compute_wind_chill (num1, num2);
printf ("\nTotal Extreme Values: %d\n", ext1);
printf ("\nDeg. C\t Deg. F\t 40%%\t 50%%\t 60%%\t"
" 70%%\t 80%%\t 90%%\t 100%%\n");
ext2 = compute_heat_index (num1, num2);
printf ("\nTotal Extreme Values: %d\n", ext2);
return 0;
}
/* comput and output heat index between num1 and num2 */
int compute_heat_index (int num1, int num2)
{
int celsius, ext1 = 0;
double humid = HMIN, celsius_f = 0, heat_index = 0;
for (celsius = num1; celsius <= num2; celsius++)
{
celsius_f = (celsius * (9 / 5)) + 32;
printf ("%d\t% .2lf\t", celsius, celsius_f);
for (humid = HMIN; humid <= HMAX; humid = humid + HSTEP)
{
heat_index = c1 + (c2 * celsius_f) + (c3 * humid) +
(c4 * humid * celsius_f) + (c5 * pow (celsius, 2)) +
(c6 * pow (humid, 2)) + (c7 * pow (celsius, 2) * humid) +
(c8 * celsius * pow (humid, 2)) +
(c9 * pow (celsius, 2) * pow (humid, 2));
if (heat_index < 80)
printf ("x\t");
else
printf ("% .2lf\t", heat_index);
}
putchar ('\n');
if (celsius_f > 100) {
ext1++;
}
}
return ext1;
}
/* comput and output wind chill between num1 and num2 */
int compute_wind_chill (int num1, int num2)
{
int celsius, wind = WMIN, ext2 = 0;
double celsius_f = 0, wind_chill = 0;
for (celsius = num1; celsius <= num2; celsius++)
{
celsius_f = (celsius * (9 / 5)) + 32;
printf ("%d\t% .2lf\t", celsius, celsius_f);
for (wind = WMIN; wind <= WMAX; wind = wind + WSTEP)
{
wind_chill = d1 + (d2 * celsius_f) - (d3 * wind) +
(d4 * celsius_f * wind);
if (wind_chill > 50)
printf (" x\t");
else
printf ("% .2lf\t", wind_chill);
}
putchar ('\n');
if (celsius_f < -20) {
ext2++;
}
}
return ext2;
}
Example Use/Output
$ ./bin/windchill
Input a range of temps in deg. C, (e.g. t1 t2): 45 55
error: values must be between -20 - 50.
Input a range of temps in deg. C, (e.g. t1 t2): 45 50
Deg. C Deg. F 5mph 10mph 15mph 20mph 25mph 30mph 35mph 40mph
45 77.00 x x 40.41 26.25 12.09 -2.07 -16.23 -30.40
46 78.00 x x 47.44 35.42 23.39 11.37 -0.66 -12.68
47 79.00 x x x 44.58 34.69 24.80 14.92 5.03
48 80.00 x x x x 45.99 38.24 30.49 22.74
49 81.00 x x x x x x 46.07 40.45
50 82.00 x x x x x x x x
Total Extreme Values: 0
Deg. C Deg. F 40% 50% 60% 70% 80% 90% 100%
45 77.00 99.68 99.21 98.74 98.27 97.80 97.32 96.85
46 78.00 101.06 100.58 100.10 99.61 99.13 98.65 98.17
47 79.00 102.43 101.93 101.44 100.95 100.46 99.96 99.47
48 80.00 103.78 103.28 102.78 102.27 101.77 101.27 100.76
49 81.00 105.13 104.61 104.10 103.59 103.07 102.56 102.04
50 82.00 106.46 105.93 105.41 104.89 104.36 103.84 103.31
Total Extreme Values: 0
note: one glaring error is your integer division error in your conversion to Fahrenheit. You can remedy that by insuring floating point division of your conversion factor:
celsius_f = (celsius * (9.0 / 5)) + 32;
Making that one change will have a dramatic impact on your calculations, e.g.
$ ./bin/windchill
Input a range of temps in deg. C, (e.g. t1 t2): 45 50
Deg. C Deg. F 5mph 10mph 15mph 20mph 25mph 30mph 35mph 40mph
45 113.00 x x x x x x x x
46 114.80 x x x x x x x x
47 116.60 x x x x x x x x
48 118.40 x x x x x x x x
49 120.20 x x x x x x x x
50 122.00 x x x x x x x x
Total Extreme Values: 0
Deg. C Deg. F 40% 50% 60% 70% 80% 90% 100%
45 113.00 170.20 168.93 167.65 166.37 165.09 163.81 162.53
46 114.80 173.15 171.84 170.54 169.23 167.92 166.61 165.30
47 116.60 176.09 174.75 173.42 172.08 170.74 169.40 168.06
48 118.40 179.01 177.65 176.28 174.92 173.55 172.18 170.81
49 120.20 181.92 180.53 179.14 177.74 176.35 174.95 173.56
50 122.00 184.82 183.40 181.98 180.55 179.13 177.71 176.28
Total Extreme Values: 0
You have some more work to do... You can start by reviewing The Heat Index Equation (which appears to be where your constants come from -- but note you are missing the correction factors and you need to pay careful attention to the units of humidity). Then follow up by looking at Wind Chill paying careful attention to the exponent on the wind. When you correct your formula, you will then need to link against the math library, so add -lm to your compile string. (that's little-'L'm). Once you correct your logic, you should see something similar to the following output.
(note: with the extreme values over a temperature range from -20 to 50, I get 164 wind_chill extremes and 332 heat_index extremes)
$ ./bin/windchill
Input a range of temps in deg. C, (e.g. t1 t2): 10 45
Wind Chill:
Deg. C Deg. F 5mph 10mph 15mph 20mph 25mph 30mph 35mph 40mph
10 50.00 47.77 45.59 44.19 43.15 42.31 41.59 40.98 40.43
11 51.80 49.87 47.80 46.48 45.50 44.70 44.02 43.44 42.92
12 53.60 51.96 50.02 48.77 47.84 47.09 46.45 45.90 45.41
13 55.40 54.06 52.23 51.06 50.19 49.48 48.88 48.36 47.90
14 57.20 56.16 54.45 53.35 52.53 51.87 51.31 50.82 50.39
15 59.00 58.26 56.66 55.64 54.88 54.26 53.74 53.28 52.88
16 60.80 60.36 58.88 57.93 57.22 56.65 56.16 55.74 55.37
17 62.60 62.45 61.09 60.22 59.57 59.04 58.59 58.21 57.86
18 64.40 x 63.30 62.51 61.91 61.43 61.02 60.67 60.35
19 66.20 x 65.52 64.80 64.26 63.82 63.45 63.13 62.85
20 68.00 x 67.73 67.09 66.60 66.21 65.88 65.59 65.34
21 69.80 x x 69.38 68.95 68.60 68.31 68.05 67.83
22 71.60 x x x 71.29 70.99 70.74 70.51 70.32
23 73.40 x x x x 73.38 73.16 72.98 72.81
24 75.20 x x x x x x x x
...
Total Extreme Values: 0
Heat Index:
Deg. C Deg. F 40% 50% 60% 70% 80% 90% 100%
...
26 78.80 x x x x x x x
27 80.60 80.35 81.35 82.55 83.94 85.53 87.32 89.31
28 82.40 81.80 83.21 85.01 87.20 89.78 92.75 96.10
29 84.20 83.49 85.39 87.86 90.91 94.53 98.74 103.51
30 86.00 85.44 87.89 91.10 95.07 99.80 105.29 111.55
31 87.80 87.64 90.71 94.72 99.68 105.58 112.42 120.21
32 89.60 90.10 93.85 98.73 104.74 111.86 120.11 129.49
33 91.40 92.81 97.32 103.13 110.25 118.66 128.38 139.39
34 93.20 95.77 101.11 107.92 116.20 125.97 137.21 149.92
35 95.00 98.99 105.22 113.09 122.61 133.78 146.60 161.07
36 96.80 102.46 109.65 118.65 129.47 142.11 156.57 172.84
37 98.60 106.18 114.40 124.60 136.78 150.95 167.10 185.24
38 100.40 110.16 119.47 130.93 144.54 160.30 178.20 198.26
39 102.20 114.39 124.87 137.65 152.75 170.15 189.87 211.90
40 104.00 118.88 130.58 144.76 161.40 180.52 202.11 226.17
41 105.80 123.62 136.62 152.25 170.51 191.40 214.91 241.05
42 107.60 128.61 142.98 160.13 180.07 202.79 228.28 256.56
43 109.40 133.85 149.66 168.40 190.08 214.68 242.22 272.70
44 111.20 139.35 156.66 177.06 200.53 227.09 256.73 289.45
45 113.00 145.10 163.99 186.10 211.44 240.01 271.81 306.83
Total Extreme Values: 97
Look things over and let me know if you have further questions.
Look here:
celsius_f=(celsius*(9/5))+32;
In C 9/5 is not equal to 9/5 as in real math, here integer divided by integer is equal to integer too, rounded to lower value. So here 9/5 is equal to 1, not 1.8. You should use float variable type, for example
celsius_f=(celsius*(9.0/5))+32;
Another mistake is here:
compute_wind_chill(num1, num2);
printf("\nTotal Extreme Values: %d", ext1);
You are displaying float result as integer.
I am working on a code that displays a conversion table from Fahrenheit to Celsius.How can I change it so that it will start from negative value and go towards positive something like this
Fahrenhite Celcius
-10 -23.3333
-20 -28.8889
..
..
..
..
100 37.7778
my code:
#include <stdio.h>
int main()
{
float fahrenheit, celsius;
int lower, upper, step;
lower = 10;
upper = 100;
step = 10;
printf("F C\n\n");
fahrenheit = lower;
while(fahrenheit <= upper)
{
celsius = (5.0 / 9.0) * (fahrenheit - 32.0);
printf("%3.0f %6.1f\n", fahrenheit, celsius);
fahrenheit = fahrenheit + step;
}
return 0;
}
Firstly you must learn how to work this code it is so simply an clear.
Your code works for lower=10 and upper=100 you can change these values what are you want you can reach table. If you want 4 digits after the conviction
printf("%3.0f %6.4f\n", fahrenheit, celsius);
you must chage %6.1f like above
-10 is greater than -100. So,
You can put lower = -100.
Then your answer will come as expected.
F C
-100 -73.3
-90 -67.8
-80 -62.2
-70 -56.7
-60 -51.1
-50 -45.6
-40 -40.0
-30 -34.4
-20 -28.9
-10 -23.3
0 -17.8
10 -12.2
20 -6.7
30 -1.1
40 4.4
50 10.0
60 15.6
70 21.1
80 26.7
90 32.2
100 37.8
int getTempo()
{
int tempo;
//User can enter tempo in bpm
tempo = (aserveGetControl(07) / 127) * 250;
//equation to convert tempo in bpm to an integer in ms to use with aserveSleep
return ((1000/tempo) * 60);
}
program won't run past this function, get the following error:
Thread 1:EXC_ARITHMETIC (code=EXC_I386_DIV, subcode=0x0)
If, as I suppose, aserveGetControl returns an integer between 0 and 127, tempo will always be zero (unless aserveGetControl returns exactly 127), since you are performing an integer division, which truncates the result to the integer part. You should invert the division and the multiplication in both your expressions, and be ready anyway to deal with the fact that aserveGetcontrol may return 0.
When you use integer maths, you should do the multiplication(s) before division(s).
Example 1 (truncation to zero)
(100 / 127) * 250
= (0) * 250
= 0
On the other hand
(100 * 256) / 127
= 25600 / 127
= 201
Example 2 (loss of precision)
(1000 / 27) * 60
= (370) * 60
= 2220
On the other hand
(1000 * 60) / 27
= (60000) / 127
= 2222
Try this:
int getTempo()
{
int tempo;
//User can enter tempo in bpm
tempo = (aserveGetControl(07) * 250) / 127;
//equation to convert tempo in bpm to an integer in ms to use with aserveSleep
return (60 * 1000) / tempo ;
}