p2p.wrox.com Forums

p2p.wrox.com Forums (http://p2p.wrox.com/index.php)
-   BOOK: Beginning C# 3.0 : An Introduction to Object Oriented Programming ISBN: 978-0-470-26129-3 (http://p2p.wrox.com/forumdisplay.php?f=409)
-   -   Farenheight to Celcius ch 3 (http://p2p.wrox.com/showthread.php?t=75557)

Lloydering2 August 4th, 2009 09:01 PM

Farenheight to Celcius ch 3
 
Hi,

I just got my program to work, although I don't understand why it didn't work the first time. Using the formula Celcius = 5/9 * (Farenheight -32) kept giving me a zero in the celcius box no matter what number I put in Farenheight. I got frustrated and gave up. I came back to it today and the idea came to switch the formula around to : Celcius = (Farenheight - 32) * 5 / 9; and it voila it worked. My question is why did the first formula produce zero's? and simply switching the formula around seems to work.
Isn't: Celcius = 5/9 * (Farenheight -32); &
Celcius = (Farenheight - 32) * 5 / 9; The same thing? I got it to work. I supose I probably should use float for the Celcius but I dont think it matters much. Anyhow thanks for your time on this matter.

using System;
using System.Windows.Forms;

public class frmMain : Form
{
private Label label1;
private Label label2;
private Button btnCalculate;
private Label lblCelcius;
private TextBox txtCelcius;
private TextBox txtDegreesF;
#region Windows code
private void InitializeComponent()
{
this.txtDegreesF = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.btnCalculate = new System.Windows.Forms.Button();
this.lblCelcius = new System.Windows.Forms.Label();
this.txtCelcius = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// txtDegreesF
//
this.txtDegreesF.Location = new System.Drawing.Point(171, 47);
this.txtDegreesF.Name = "txtDegreesF";
this.txtDegreesF.Size = new System.Drawing.Size(100, 20);
this.txtDegreesF.TabIndex = 0;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 50);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(144, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Insert number in Farenheight:";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(58, 88);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(98, 13);
this.label2.TabIndex = 3;
this.label2.Text = "Degrees in Celcius:";
//
// btnCalculate
//
this.btnCalculate.Location = new System.Drawing.Point(184, 134);
this.btnCalculate.Name = "btnCalculate";
this.btnCalculate.Size = new System.Drawing.Size(75, 23);
this.btnCalculate.TabIndex = 4;
this.btnCalculate.Text = "Calculate";
this.btnCalculate.UseVisualStyleBackColor = true;
this.btnCalculate.Click += new System.EventHandler(this.btnCalculate_Click);
//
// lblCelcius
//
this.lblCelcius.AutoSize = true;
this.lblCelcius.Location = new System.Drawing.Point(171, 88);
this.lblCelcius.Name = "lblCelcius";
this.lblCelcius.Size = new System.Drawing.Size(0, 13);
this.lblCelcius.TabIndex = 5;
//
// txtCelcius
//
this.txtCelcius.Font = new System.Drawing.Font("Arial", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.txtCelcius.Location = new System.Drawing.Point(171, 81);
this.txtCelcius.Name = "txtCelcius";
this.txtCelcius.ReadOnly = true;
this.txtCelcius.Size = new System.Drawing.Size(100, 26);
this.txtCelcius.TabIndex = 6;
this.txtCelcius.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// frmMain
//
this.ClientSize = new System.Drawing.Size(403, 190);
this.Controls.Add(this.txtCelcius);
this.Controls.Add(this.lblCelcius);
this.Controls.Add(this.btnCalculate);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.txtDegreesF);
this.MaximizeBox = false;
this.Name = "frmMain";
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.ResumeLayout(false);
this.PerformLayout();

}
#endregion

public frmMain()
{
InitializeComponent();
}

public static void Main()
{

frmMain main = new frmMain();
Application.Run(main);
}

private void btnCalculate_Click(object sender, EventArgs e)
{
int Farenheight;
int Celcius;
bool flag;



// input step
// check farenhieght for int

flag = int.TryParse(txtDegreesF.Text, out Farenheight);
if (flag == false)
{
MessageBox.Show("Enter a number", "Input error");
txtDegreesF.Focus();
return;
}

// compute step

Celcius = (Farenheight - 32) * 5 / 9;


// display step

txtCelcius.Text = Celcius.ToString();

}





}

DrPurdum August 6th, 2009 12:18 PM

Temperature Conversion Problem
 
The reason it failed was because you used integer data types for the formula. When you converted 5/9 and assigned it into an integer data type, because integers can't express a fractional value, the result was zero. From that point on, you were working with zero for that result. If you change things to use the double data type, it would have worked correctly.

Lloydering2 August 6th, 2009 07:28 PM

Quote:

Originally Posted by DrPurdum (Post 244863)
The reason it failed was because you used integer data types for the formula. When you converted 5/9 and assigned it into an integer data type, because integers can't express a fractional value, the result was zero. From that point on, you were working with zero for that result. If you change things to use the double data type, it would have worked correctly.

Ok that answers my question of why the first formula didnt work but doesnt explain why when i took the same formula and switched it around (still using the int variables) it seems to work.

Isn't: Celcius = 5/9 * (Farenheight -32); &didnt work with int.
Celcius = (Farenheight - 32) * 5 / 9; did work with int.
Aren't those two formulas the same thing? one didnt work one did. I don't understand why?

Old Pedant August 7th, 2009 01:06 AM

Let's take a real example.

Let's say Fahrenheit is 58 degrees.

So:

Celcius = 5 / 9 * (Fahrenheit - 32)
==>> 5 / 9 * (58 - 32)
The parens are evaluated first so that
==>> 5 / 9 * 26
Because multiplication and division have the same OPERATOR PRECEDENCE (look it up), that expression is evaluated strictly LEFT TO RIGHT:
so 5 / 9 ==>> 0 (since both 5 and 9 are integers)
and then 0 * 26 ==>> 0

**************

Now consider:
Celcius = (Farenheight - 32) * 5 / 9
==>> (58 - 32) * 5 / 9
==>> 26 * 5 / 9
Again, with multiplication and division equal in precedence, the order is left to right, so:
26 * 5 ==>> 130
130 / 9 ==>> 14 (should be 14.44444444 but remember, this is INTEGER math)

So it all comes down to the order that things are done in.

Here's a related problem for you:

What is the value of 3 + 7 * 5 ??

If you said 50, go back to elementary algebra class.

Multiplication has a higher precedence than addition, so *IT* happens first. Just as if you had coded

3 + ( 7 * 5 ) ==>> 3 + 35 ==>> 38

But, again, that doesn't apply when the two operators have equal precedence. Then it's strictly left to right.

** EXCEPTION IN C++ (and C and C# and...) **
The assignment operators (= and += and *= and so on) happen RIGHT TO LEFT.

That's why you can do

x = y = 7;
a = b += 3;

The y = 7 happens first and then the x = y. Ditto for the b += 3 going first. And then the a = b means that a and b end up with the same value.

There will be a quiz Monday. No calculators allowed.





RyanL January 2nd, 2011 02:44 AM

Sorry to bug (and to bring up such an old topic), but I seem to be having a similar issue. The thing is I'm using doubles not integers, yet I'm still getting a 0 for my answer (from the 5 / 9 calculation, as far as I can tell).

Am I making a mistake someplace else?

Thanks in advance for any help!

Code:

using System;
using System.Windows.Forms;

public class frmMain : Form
{
    private TextBox txtFar;
    private TextBox txtResult;
    private Button btnCal;
    private Button btnExit;
    private Label label1;
    #region Windows code
    private void InitializeComponent()
    {
        this.label1 = new System.Windows.Forms.Label();
        this.txtFar = new System.Windows.Forms.TextBox();
        this.txtResult = new System.Windows.Forms.TextBox();
        this.btnCal = new System.Windows.Forms.Button();
        this.btnExit = new System.Windows.Forms.Button();
        this.SuspendLayout();
        //
        // label1
        //
        this.label1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
        this.label1.Location = new System.Drawing.Point(12, 9);
        this.label1.Name = "label1";
        this.label1.Size = new System.Drawing.Size(139, 20);
        this.label1.TabIndex = 0;
        this.label1.Text = "Enter Fahrenheit Temp";
        this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
        //
        // txtFar
        //
        this.txtFar.Location = new System.Drawing.Point(172, 9);
        this.txtFar.Name = "txtFar";
        this.txtFar.Size = new System.Drawing.Size(100, 20);
        this.txtFar.TabIndex = 1;
        //
        // txtResult
        //
        this.txtResult.Location = new System.Drawing.Point(13, 82);
        this.txtResult.Multiline = true;
        this.txtResult.Name = "txtResult";
        this.txtResult.ReadOnly = true;
        this.txtResult.Size = new System.Drawing.Size(259, 46);
        this.txtResult.TabIndex = 2;
        //
        // btnCal
        //
        this.btnCal.Location = new System.Drawing.Point(12, 43);
        this.btnCal.Name = "btnCal";
        this.btnCal.Size = new System.Drawing.Size(75, 23);
        this.btnCal.TabIndex = 3;
        this.btnCal.Text = "&Convert";
        this.btnCal.UseVisualStyleBackColor = true;
        this.btnCal.Click += new System.EventHandler(this.btnCal_Click);
        //
        // btnExit
        //
        this.btnExit.Location = new System.Drawing.Point(197, 43);
        this.btnExit.Name = "btnExit";
        this.btnExit.Size = new System.Drawing.Size(75, 23);
        this.btnExit.TabIndex = 4;
        this.btnExit.Text = "E&xit";
        this.btnExit.UseVisualStyleBackColor = true;
        this.btnExit.Click += new System.EventHandler(this.btnExit_Click);
        //
        // frmMain
        //
        this.ClientSize = new System.Drawing.Size(284, 147);
        this.Controls.Add(this.btnExit);
        this.Controls.Add(this.btnCal);
        this.Controls.Add(this.txtResult);
        this.Controls.Add(this.txtFar);
        this.Controls.Add(this.label1);
        this.Name = "frmMain";
        this.Text = "Temp Converter";
        this.ResumeLayout(false);
        this.PerformLayout();

    }
    #endregion

    public frmMain()
    {
        InitializeComponent();
    }

    public static void Main()
    {
        frmMain main = new frmMain();
        Application.Run(main);
    }

    private void btnCal_Click(object sender, EventArgs e)
    {
        bool flag;
        double Farenheit;
        double Celcius;

        flag = double.TryParse(txtFar.Text, out Farenheit);
        if (flag == false)
        {
            MessageBox.Show("Enter a number!");
            txtFar.Focus();
            return;
        }

        Celcius = 5 / 9 * (Farenheit - 32);

        txtResult.Text = Farenheit.ToString() + " degrees Fahrenheit is equal to " + Celcius.ToString() + " degrees Celsius";
        txtResult.Visible = true;
   
    }

    private void btnExit_Click(object sender, EventArgs e)
    {
        Close();
    }

}


DrPurdum January 2nd, 2011 10:11 AM

Temperature conversion problem
 
The problem is with the line:

Celcius = 5 / 9 * (Farenheit - 32);

When the compiler sees this line, it thinks: "Ok, I have integer constants 5, 9, and 32. It will perform the parenthesized calculation (Farenheit - 32) first. Because an integer constant is used, the expression is evaluated as an integer. Since the 5 and 9 are also viewed as integer constants, even thought the calculation evaluates to 5/9 = .5555555559, because the compiler thinks it's an integer expression which can't support decimal values, it sees the calculation as zero. It then multiplies the parenthesized expression (i.e., Farenheit - 32) as an integer result and then multiplies that by zero. The result will always be zero.

The correction is easy:

Celcius = 5.0 / 9.0 * (Farenheit - 32.0);

by adding the ".0" to each constant, the compiler now knows you want to perform floating point, not integer, operations. The result is that the double-precision operation on the right side of the assignment is now done as a floating point operation.

BTW, while it would not make much difference in this case, division is the slowest of the basic math operations. If this were in a lengthy loop, you could make it execute faster using:

Celcius = .5555555559 * (Farenheit - 32); // .5555555559 is 5/9

Note: The comment should be added, as it documents the "magic number". You could also use a numeric constant instead of the magic number:

const double FIVENINTHS = .555555555559;

and change the code to:

Celcius = FIVENINTHS * (Farenheit - 32); // .5555555559 is 5/9

I would still leave the comment in the code. I hope this helps.

DrPurdum January 2nd, 2011 10:14 AM

Opps!
 
The last code line still needs the ".0" added to 32:

Celcius = FIVENINTHS * (Farenheit - 32.0);


One of the dangers of cut-and-paste! Sorry 'bout that...

RyanL January 2nd, 2011 04:58 PM

Thanks so much for the quick reply!

Just so I understand, even though I passed Celcius as a double, it still sees the operands in the expression (just hit chapter 4, sorry if I'm using the terminology incorrectly) as integers because they don't have a decimal value?

This is a fantastic book, btw - the first I've read that actually is written for beginners without being too simplified and transitions into new subjects in a logical way.

DrPurdum January 3rd, 2011 10:37 AM

Program constants
 
Yep, that's right.

Any time the compiler sees a numeric constant in the source code without a trailing decimal point, it will automatically assume it's an integer. If you want it to be a floating point number, as is the case here, you should add ".0" after the numeric constant to inform the compiler you want to do floating point operations on the number. Likewise, if you want to use a long data type constant, you should add a capital ell after the number, as in "55L", which would tell the compiler you want to use a long data type. (A lower case ell is difficult to read, as it looks like a pure number: "55l" which uses an ell, but looks like a one's digit.) Also, these data type modifiers (see suffixes, data types in the book's Index for a more complete list) help document any reader of your code that the number is something other than an integer number.

Thanks for the kind words about the book...it's sincerely appreciated.

RyanL January 4th, 2011 01:59 AM

Fantastic, thanks again!


All times are GMT -4. The time now is 05:58 AM.

Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.