C/C++ C++. Celsius to Fahren. conver; What temp R they = ?

  • Thread starter Thread starter burton95
  • Start date Start date
  • Tags Tags
    celsius
AI Thread Summary
The discussion revolves around writing a program to find the temperature at which Celsius and Fahrenheit are equal, specifically at -40 degrees. The initial code provided incorrectly outputs -43 instead of -40 due to a misunderstanding of the loop's logic. The user is advised to add print statements to debug the values of Celsius and Fahrenheit during iterations. The issue stems from the order of operations in the loop, where the Celsius temperature is decremented before the comparison, leading to an off-by-one error. The conversation also touches on the challenges of using floating-point arithmetic in programming, highlighting that integer calculations yield exact results, while floating-point comparisons can lead to inaccuracies. The importance of understanding loop conditions and potential pitfalls in programming, such as off-by-one errors, is emphasized. The user ultimately resolves the issue, realizing that careful attention to the loop's structure is crucial for accurate results.
burton95
Messages
54
Reaction score
0
I must write a program that finds the temperature, as an integer, that is the same in both Celsius and Fahrenheit. The formula for this is

F=(9/5)C+32

The program should create two integer variables for the temperature in Celsius and Fahrenheit. Initialize the temperature to 100 degrees Celsius. In a loop, decrement the Celsius value and compute the corresponding temperature in Fahrenheit until the values are the same.

my code
Code:
#include <iostream>
using namespace std;

int main()
{
	int c_temp = 100;
	int f_temp = 212;	while (c_temp != f_temp)
	{
		f_temp = ((9 * c_temp) / 5) + 32;
		c_temp--;
	}
	cout << "The temperature when they are both the same is: " << c_temp << endl;
}
Answer is - 40 but I keep getting -43. What am I missing? I tried changing int to doubles and then it wouldn't run. Thanks

Anthony
 
Last edited by a moderator:
Technology news on Phys.org
I only see 1 problem but it doesn't explain your result.
Add into your loop after you calculate f_temp something like

Code:
cout << "c_temp: " << c_temp << " vs f_temp: " << f_temp << endl;
That will allow you to see what the code believes is happening.

Also note cause you decrements c_temp, then do the check at the start of the loop if you immediately output c_temp it will be 1 less than the correct result.
what I mean is
c_temp is -40
f_temp is calc'd to be -40
c_temp is decremented to -41
while loop condition fails
output c_temp as -41
 
  • Like
Likes 1 person
thanks cpscdave, I added your print line code and obviously it doesn't stop @ -40. I don't get it.

c_temp: -34 vs f_temp: -29
c_temp: -35 vs f_temp: -31
c_temp: -36 vs f_temp: -32
c_temp: -37 vs f_temp: -34
c_temp: -38 vs f_temp: -36
c_temp: -39 vs f_temp: -38
c_temp: -40 vs f_temp: -40
c_temp: -41 vs f_temp: -41
c_temp: -42 vs f_temp: -43
The temperature when they are both the same is: -43
 
Oh and berkman asked if I could add code tags. Its he referencing code tags in the body of the post or as a tag for the post?
 
Your problem is you aren't following directions. The problem says to do the following:
In a loop, decrement the Celsius value and compute the corresponding temperature in Fahrenheit until the values are the same.​
You aren't doing that. Here's what you are doing:
In a loop, compute the corresponding temperature in Fahrenheit and decrement the Celsius value until the values are the same.​

A lesser problem: You aren't computing the correct values at times. For example, -36 C and -32.8 F are the same temperature. Your program reports a value of -32 F. It would be better to report a value of -33 F as the integral value of that -32.8 F value.
 
  • Like
Likes 1 person
Thanks DH. It says to use int's so that is what I'm doing. Seems pretty obvious now.
 
OHHHHHH I know why your loop isn't working now :)

A couple things. Berkman means in the body of the post, like how I posted the cout code.

I don't want to tell you exactly why your loop isn't working. There is good learning in figuring it out on your own. But I'll give you a hint. The issue you are having is similar to the output problem I referenced early.
Ask yourself if the cout is saying that c_temp and f_temp are equal (when they both are -40) why isn't the loop exiting and why when they aren't equal (-42 vs -43) does the loop exit :)
 
burton95 said:
Thanks DH. It says to use int's so that is what I'm doing.
That's why I wrote that second and also added that this is a lesser problem.

Did you read the first part of my post?


Seems pretty obvious now.
Does that mean you have solved the problem?
 
The return value is correct, -40. I have a feeling getting loops to run the correct amount of times is going to be tricky topic for me for a while. Thanks to both of you.
 
  • #10
burton95 said:
The return value is correct, -40. I have a feeling getting loops to run the correct amount of times is going to be tricky topic for me for a while. Thanks to both of you.

So you figured it out??

Start and stop conditions for loops is something that can be tricky at time.

For loops the way I do things generally is:
If I know how many times exactly a loop needs to be ran: For loop
If the loop needs to run AT least 1 or more times: do while loop
If the loop needs to run 0 or more times: while loop

This problem would've fallen into the do while category the way you set it up :)
 
  • #11
burton95 said:
I have a feeling getting loops to run the correct amount of times is going to be tricky topic for me for a while. Thanks to both of you.
You need to take care. Errors similar to yours pop up all the time. Suppose you need to make a linear fence 100 meters long using 10 meter long sections of fencing. How many fenceposts do you need? (The answer is 11, not 10.) A similar error: You have 10 fenceposts. How many sections of fencing do you need to build a linear fence using all your fenceposts? (The answer is 9, not 10.) Thinking the answer to these questions is ten occurs so frequently that these mistakes are called fencepost errors.

These two kinds of fencepost errors are in the larger class of off-by-one errors. Yours is essentially an off-by-one error. You need to watch out for them.
 
  • #12
FactChecker said:
3) When you tried a floating point calculation, C and F may never have been exactly equal (to the nearest 2^(-64) ).
Integers between -224 and 224 are be stored exactly in a single precision IEEE floating point number. For double precision numbers, integers between -253 and 253 are be stored exactly.

A value of -40 will be stored exactly, and the floating point computation (9.0*40)/5.0 + 32.0 will be exactly 40.0.
 
  • #13
D H said:
Integers between -224 and 224 are be stored exactly in a single precision IEEE floating point number. For double precision numbers, integers between -253 and 253 are be stored exactly.

A value of -40 will be stored exactly, and the floating point computation (9.0*40)/5.0 + 32.0 will be exactly 40.0.
The calculation is only an integer every 5'th iteration. My comment was just to warn about testing for equality of floats to terminate the loop. It is pure luck that the solution of x=9x/5+32 is an integer.
 
Last edited:
  • #14
FactChecker said:
It is pure luck that the solution of x=9x/5+32 is an integer.

When x = -40, or any fairly small multiple of 5, it is not "pure luck", if your computer uses IEEE arithmetic.

Some non-IEEE hardware did give nasty surprises over this. In particular the early Cray supercomputers didn't have any special-purpose hardware for division, but calculated a/b as a*reciprocal(b), where "reciprocal" was calculated by a software function, using an iterative algorithm. A reciprocal like 1/5 can NOT be represented exactly as a binary value, so a/5 was never an exact value, unless a = 0.

In general the warning about testing equality of floats is valid, of course.
 
  • #15
AlephZero said:
When x = -40, or any fairly small multiple of 5, it is not "pure luck", if your computer uses IEEE arithmetic.

Some non-IEEE hardware did give nasty surprises over this. In particular the early Cray supercomputers didn't have any special-purpose hardware for division, but calculated a/b as a*reciprocal(b), where "reciprocal" was calculated by a software function, using an iterative algorithm. A reciprocal like 1/5 can NOT be represented exactly as a binary value, so a/5 was never an exact value, unless a = 0.

In general the warning about testing equality of floats is valid, of course.

I thought the same thing till a couple of weeks ago, when someone on another post gave this example:
Code:
Perl code:
$x =  25.4 / 10.0  *  1.0 / 2.54 ;
$y = (25.4 / 10.0) * (1.0 / 2.54);
printf ("%g %s %g\n", $x, (($x == $y) ? "=" : "!="), $y);
I ran it on a Wintel PC and got: "1 != 1"
So IEEE 754 does not guarantee as much as I thought it did.
 
  • #16
That was my example.

Nonetheless, AlephZero is correct. (9.0*x)/5.0 is exact when x is a "small" multiple of 5, where "small" means |x|≤9007199254740990. There's no problem here since 40 is much less than 9007199254740990.

Compare to (9.0/5.0)*x. That's where luck might kick in. Lesson to be learned: Watch how you arrange your expressions. The math you learned in school doesn't quite apply to floating point formats such as IEEE 754. Floating point arithmetic isn't commutative or associative. One might think that (9.0*x)/5.0 and (9.0/5.0)*x should yield the same result, but they oftentimes don't.

This is all a bit off-topic since the OP was specifically told to use integers. There's no problem with an exact comparison for integers.
 
  • #17
D H said:
That was my example.

Nonetheless, AlephZero is correct. (9.0*x)/5.0 is exact when x is a "small" multiple of 5, where "small" means |x|≤9007199254740990. There's no problem here since 40 is much less than 9007199254740990.
I am curious about how you can identify the problem calculations like your example versus others like this that are not a problem.
This is all a bit off-topic since the OP was specifically told to use integers. There's no problem with an exact comparison for integers.
The OP mentioned that a version using floating point calculations did not run. He didn't say exactly what that code was. I suspect that it did not terminate because he was decrementing C in the wrong place and the solution was not at the integral C values of his loop.
 
  • #18
AlephZero said:
When x = -40, or any fairly small multiple of 5, it is not "pure luck", if your computer uses IEEE arithmetic.
One bit of "pure luck" is that the solution of the equation x = 9x/5 + 32 is an integer value exactly divisible by 5 and that the sequence of integer calculations with intermediate truncations gives the correct value.

Regarding the "pure luck" of testing equality of two floating point calculations, I do not know how to distinguish a calculation that gives a false (-40 != -40) result from one that gives a correct result (-40 == -40) result where the two sides are calculated differently.
 
Last edited:
  • #19
FactChecker said:
I am curious about how you can identify the problem calculations like your example versus others like this that are not a problem.
A short list, by no means complete.
  • Know what an inexact result is, and know what causes them. 9.0/5.0 is inexact. 40.0/5.0 is not (it's exact).
  • Know how rounding works. Consider the following:
    Code:
    int rintx  = std::lrint (x);
    int roundx = std::lround (x);
    int floorx = std::floor (x + 0.5);
    int ceilx  = std::ceil (x - 0.5);
    int intx   = int(x + std::copysign(0.5, x));
    What's the difference between the above five rounding schemes?
  • Know what ULP means.
  • Know all the ways in which a calculation can suffer massive loss of precision.
 

Similar threads

Back
Top