8

I'm trying to convert a Fahrenheit temperature into Celsius.
doing the following I'm always getting zero:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Celcius_Farenheit_Converter
{
class Program
{

    static double Celcius(double f)
    {
        double c = 5/9*(f - 32);

        return c;
    }
    static void Main(string[] args)
    {
        string text = "enter a farenheit tempature";
        double c = Celcius(GetTempature(text));
        Console.WriteLine("the tempature in Celicus is {0}", c);

        Console.ReadKey(true);

    }

    static double GetTempature(string text)
    {
        Console.WriteLine(text);
        bool IsItTemp = false;
        double x = 0;

        do
        {
            IsItTemp = double.TryParse(Console.ReadLine(), out x);
        } while (!IsItTemp);

        return x;

    }
}
}

can you help me fix it?

Mathieu Guindon
  • 69,817
  • 8
  • 107
  • 235
user2723261
  • 541
  • 2
  • 7
  • 12
  • 1
    Instead of passing temperatures about in numeric variables, why not use a struct to define a temperature type. There's a good example here: http://stackoverflow.com/questions/3995920/using-real-world-units-instead-of-types. That will make your code simpler to maintain in the long run, as well as improving the readability. – JohnLBevan Aug 30 '13 at 22:37

5 Answers5

33

5/9 performs an integer division—that is, it always discards the fractional part—so it will always return 0.

5.0/9.0 performs floating-point division, and will return the expected 0.55555...

Try this instead:

static double Celcius(double f)
{
    double c = 5.0/9.0 * (f - 32);

    return c;
}

Further Reading

p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • 1
    It should Be sufficient to write it like this:5/9f * (f - 32) in other words, you only have to specify that one operand is a floating point variable – Frederik Gheysels Aug 30 '13 at 22:47
  • 1
    Technically you should have a guard to prevent c going below −273.15, or at least throw an exception. – Moop Aug 30 '13 at 22:59
  • 2
    @Moop Unless you're trying to represent a temperature *difference* larger than 273.15° C or a [temperature below 0° K](https://en.wikipedia.org/wiki/Negative_temperature)--which isn't entirely unheard of. In both cases the input to this function would be less than -459.67° F, so one would assume that was the actual intent. – p.s.w.g Aug 30 '13 at 23:04
  • @pswg I'll give you the difference, not the below 0 Kelvin – Moop Aug 30 '13 at 23:10
  • I'd recommend to always do the division last in floating point math. It reduces and round-off errors. So `5*(f-32)/9` would work just fine, with implicit conversion from `int` to `float`. – John Alexiou Aug 30 '13 at 23:14
  • @p.s.w.g: Nope; Moop was correct the first time. If one is converting delta-temperatures from F to C then the formula is simply deltaF = 9.0 / 5.0 * deltaC, with no 32 degree offset. Your formula only applies to measures of temperature points, not deltas. – Pieter Geerkens Aug 31 '13 at 02:21
12

Change your integer division to floating point division like;

double c = (5.0 / 9.0) * (f - 32);

From C# Specification $7.7.2 Division operator;

Integer division:

The division rounds the result towards zero, and the absolute value of the result is the largest possible integer that is less than the absolute value of the quotient of the two operands. The result is zero or positive when the two operands have the same sign and zero or negative when the two operands have opposite signs.

As Frederik said, only chaning one of your variables to floating point type is also enough for your calculation. (5 / 9f or 5f / 9 gives the right solution)

Community
  • 1
  • 1
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
2

Earlier in the comments I suggested the option of using a struct to encapsulate your temperature conversion logic. I've knocked up a rough hash below (only partially tested) should it be of interest:

public struct Temperature: IComparable
{
    #region fields
    double value;
    TemperatureUnit unit;
    #endregion fields
    #region constructors
    public Temperature(double value, TemperatureUnit unit)
    {
        AssertUnitNotNull(unit);
        AssertValueNotBelowAbsZero(value, unit);
        this.value = value;
        this.unit = unit;
    }
    public Temperature(Temperature temp, TemperatureUnit unit)
    {
        AssertUnitNotNull(unit);
        this.value = ConvertUnit(temp.value, temp.unit, unit);
        this.unit = unit;
    }
    #endregion constructors
    #region properties
    public double Value
    {
        get { return this.value; }
        set 
        {
            AssertValueNotBelowAbsZero(value, this.unit);
            this.value = value; 
        }
    }
    public TemperatureUnit Unit
    {
        get { return this.unit; }
        set 
        {
            AssertUnitNotNull(value);
            if (this.unit != value)
            {
                this.value = ConvertUnit(this.value, this.unit, value);
                this.unit = value;
            }
        }
    }
    #endregion properties
    #region methods
    #region overridden methods
    public override bool Equals(object obj)
    {
        return this.CompareTo(obj) == 0;
    }
    public override int GetHashCode()
    {
        return this.unit.ToKelvin(value).GetHashCode();
    }
    const string OutputFormat = "{0}{1}";
    public override string ToString()
    {
        return string.Format(OutputFormat, this.value, this.unit.Symbol);
    }
    #endregion overridden methods
    public int CompareTo(object obj)
    {
        Temperature? t = obj as Temperature?;
        if (!t.HasValue) return -1;
        return this.unit.ToKelvin(value).CompareTo(t.Value.unit.ToKelvin(t.Value.value));   
    }
    #region operator overloads
    public static Temperature operator +(Temperature a, double b)
    {
        return new Temperature(a.value + b, a.unit);
    }
    public static Temperature operator +(Temperature a, Temperature b)
    {
        return a + ConvertUnit(b.value, b.unit, a.unit);
    }
    public static Temperature operator +(Temperature a, TemperatureUnit b)
    {
        return new Temperature(a, b);
    }
    public static Temperature operator -(Temperature a, double b)
    {
        return new Temperature(a.value - b, a.unit);
    }
    public static Temperature operator -(Temperature a, Temperature b)
    {
        return a - ConvertUnit(b.value, b.unit, a.unit);
    }
    public static Temperature operator ++(Temperature a)
    {
        return new Temperature(a.value + 1.0, a.unit);
    }
    public static Temperature operator --(Temperature a)
    {
        return new Temperature(a.value - 1.0, a.unit);
    }
    public static Temperature operator /(Temperature a, double b)
    {
        return new Temperature(a.value / b, a.unit);
    }
    public static Temperature operator *(Temperature a, double b)
    {
        return new Temperature(a.value * b, a.unit);
    }
    #endregion operator overloads
    #region helper methods
    private static double ConvertUnit(double value, TemperatureUnit from, TemperatureUnit to)
    {
        return to.FromKelvin(from.ToKelvin(value));
    }
    #endregion helper methods
    #endregion methods
    #region static validation methods
    private static void AssertUnitNotNull(TemperatureUnit unit)
    {
        if (unit == null) throw new ArgumentNullException();
    }
    private static void AssertValueNotBelowAbsZero(double value, TemperatureUnit unit)
    {
        if (unit.ToKelvin(value) < 0.0) throw new TemperatureIsBelowAbsoluteZeroException(value,unit);
    }
    #endregion static validation methods

}

public sealed class TemperatureUnit
{
    #region delegate definitions
    delegate double Conversion(double source);
    #endregion delegate definitions

    #region attributes
    readonly string name;
    readonly string symbol;
    //base all functions around Kelvin since that allows us to restrict values to zero and above
    readonly Conversion fromKelvin;
    readonly Conversion toKelvin;
    #endregion attributes

    #region constructors
    private TemperatureUnit(string name, string symbol, Conversion fromKelvin, Conversion toKelvin)
    {
        this.name = name;
        this.symbol = symbol;
        this.fromKelvin = fromKelvin;
        this.toKelvin = toKelvin;
    }
    #endregion constructors

    #region properties
    public string Name { get { return this.name; } }
    public string Symbol { get { return this.symbol; } }
    #region defined units
    public static TemperatureUnit Kelvin = new TemperatureUnit("Kelvin", "\u212A", delegate(double d) { return d; }, delegate(double d) { return d; });
    public static TemperatureUnit Celcius = new TemperatureUnit("Celcius", "\u2103", KelvinToCelcius, CelciusToKelvin);
    public static TemperatureUnit Farenheit = new TemperatureUnit("Farenheit", "\u2109", KelvinToFarenheit, FarenheitToKelvin);
    public static TemperatureUnit Rankine = new TemperatureUnit("Rankine", "\u00B0Ra", KelvinToRankine, RankineToKelvin);
    public static TemperatureUnit Romer = new TemperatureUnit("R\u03B8mer", "\u00B0R\u03B8", KelvinToRomer, RomerToKelvin);
    public static TemperatureUnit Newton = new TemperatureUnit("Newton", "\u00B0N", KelvinToNewton, NewtonToKelvin);
    public static TemperatureUnit Delisle = new TemperatureUnit("Delisle", "\u00B0D", KelvinToDelisle, DelisleToKelvin);
    public static TemperatureUnit Reaumur = new TemperatureUnit("R\u00E9amur", "\u00B0R\u00E9", KelvinToReaumur, ReaumurToKelvin);
    #endregion defined units
    #endregion properties

    #region functions
    public double FromKelvin(double kelvin)
    {
        return this.fromKelvin(kelvin);
    }
    public double ToKelvin(double value)
    {
        return this.toKelvin(value);
    }
    #endregion functions

    #region overridden methods
    public override bool Equals(object obj)
    {
        TemperatureUnit tu = obj as TemperatureUnit;
        if (tu == null) return false;
        return this.name.Equals(tu.name);
    }
    public override int GetHashCode()
    {
        return this.name.GetHashCode();
    }
    public override string ToString()
    {
        return this.name.ToString();
    }
    #endregion overridden methods

    #region static conversion functions
    #region Celcius
    const double KelvinToCelciusOffset = -273.15;
    public static double CelciusToKelvin(double celcius)
    {
        return celcius - KelvinToCelciusOffset;
    }
    public static double KelvinToCelcius(double kelvin)
    {
        return kelvin + KelvinToCelciusOffset;
    }
    #endregion Celcius
    #region Fahrenheit
    //Fahrenheit    [°F] = [K] × 9⁄5 − 459.67   [K] = ([°F] + 459.67) × 5⁄9
    const double KelvinToFarenheitMultiplier = 9.0 / 5.0;
    const double KelvinToFarenheitOffset = -459.67;
    public static double FarenheitToKelvin(double farenheit)
    {
        return (farenheit - KelvinToFarenheitOffset) / KelvinToFarenheitMultiplier;
    }
    public static double KelvinToFarenheit(double kelvin)
    {
        return kelvin * KelvinToFarenheitMultiplier + KelvinToFarenheitOffset;
    }
    #endregion Fahrenheit
    #region Rankine
    const double KelvinToRankineMultiplier = KelvinToFarenheitMultiplier;
    public static double RankineToKelvin(double rankine)
    {
        return rankine / KelvinToRankineMultiplier;
    }
    public static double KelvinToRankine(double kelvin)
    {
        return kelvin * KelvinToRankineMultiplier;
    }
    #endregion Rankine
    #region Romer
    //[K] = ([°Rø] − 7.5) × 40⁄21 + 273.15  [°Rø] = ([K] − 273.15) × 21⁄40 + 7.5
    const double KelvinToRomerMultiplier = 21.0 / 40.0;
    const double KelvinToRomerOffset1 = KelvinToCelciusOffset;
    const double KelvinToRomerOffset2 = 7.5;
    public static double RomerToKelvin(double romer)
    {
        return (romer - KelvinToRomerOffset2) / KelvinToRomerMultiplier - KelvinToRomerOffset1;
    }
    public static double KelvinToRomer(double kelvin)
    {
        return (kelvin + KelvinToRomerOffset1) * KelvinToRomerMultiplier + KelvinToRomerOffset2;
    }
    #endregion Romer
    #region Newton
    //[K] = [°N] × 100⁄33 + 273.15  [°N] = ([K] − 273.15) × 33⁄100
    const double KelvinToNewtonMultiplier = 33.0 / 100.0;
    const double KelvinToNewtonOffset = KelvinToCelciusOffset;
    public static double NewtonToKelvin(double newton)
    {
        return (newton / KelvinToNewtonMultiplier) - KelvinToNewtonOffset;
    }
    public static double KelvinToNewton(double kelvin)
    {
        return (kelvin + KelvinToNewtonOffset) * KelvinToNewtonMultiplier;
    }
    #endregion Newton
    #region Delisle
    //[K] = 373.15 − [°De] × 2⁄3    [°De] = (373.15 − [K]) × 3⁄2
    const double KelvinToDelisleMultiplier = 1.5;
    const double KelvinToDelisleOffset = 373.15;
    public static double DelisleToKelvin(double delisle)
    {
        return KelvinToDelisleOffset - delisle / KelvinToDelisleMultiplier;
    }
    public static double KelvinToDelisle(double kelvin)
    {
        return (KelvinToDelisleOffset - kelvin) * KelvinToDelisleMultiplier;
    }
    #endregion Delisle
    #region Reaumur
    //[K] = [°Ré] × 5⁄4 + 273.15    [°Ré] = ([K] − 273.15) × 4⁄5
    const double KelvinToReaumurMultiplier = 4.0 / 5.0;
    const double KelvinToReaumurOffset = KelvinToCelciusOffset;
    public static double ReaumurToKelvin(double reaumur)
    {
        return reaumur / KelvinToReaumurMultiplier - KelvinToReaumurOffset;
    }
    public static double KelvinToReaumur(double kelvin)
    {
        return (kelvin + KelvinToReaumurOffset) * KelvinToReaumurMultiplier;
    }
    #endregion Reaumur
    #endregion static conversion functions

}

public class TemperatureIsBelowAbsoluteZeroException : Exception
{
    public TemperatureIsBelowAbsoluteZeroException() : base() { }
    public TemperatureIsBelowAbsoluteZeroException(string message) : base(message) { }
    public TemperatureIsBelowAbsoluteZeroException(string message, Exception innerException) : base(message,innerException) { }
    public TemperatureIsBelowAbsoluteZeroException(System.Runtime.Serialization.SerializationInfo info,System.Runtime.Serialization.StreamingContext context) : base(info,context) { }

    const string ErrorMessageFormat = "Value '{0}{1}' is below absolute zero!";
    public TemperatureIsBelowAbsoluteZeroException(double value, TemperatureUnit unit) : base(string.Format(ErrorMessageFormat, value, unit.Symbol)) { }
}
JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class TempConvert
    {
        static void Main(string[] args)
        {

            //Variables declared to hold and test conversion
            //floats used to avoid int calculation errors
            float originalFarenheit;
            float centigrade;
            float returnFarenheit;

            Console.Write("Enter Temperature (Farenheit): ");      //take temp to be converted
            originalFarenheit = float.Parse(Console.ReadLine());   //hold as float var
            centigrade = ((originalFarenheit - 32) / 9) * 5;       //Convert to centrigrade
            returnFarenheit = ((centigrade / 5) * 9) + 32;         //test conversion by reversing

            Console.WriteLine("Centigrade = :" + centigrade);              //Display result
            Console.WriteLine("Return Farenheit = :" + returnFarenheit);   //Test result

            Console.ReadKey();
        }
    }
}
Milodin
  • 21
  • 8
  • 1
    While this does get around the floating point problem; I don't see it as adding anything to the other answers. Its also non-obvious *why* this works (all division ops have a `float` operand), so it at *least* needs an accompanying explanation. – BradleyDotNET Nov 07 '14 at 00:54
  • Yeah, you are right - it does need comments. I just thought it was a bit simpler than some of the other answers and seeing as I had just done this assignment when signing up I thought I would post. – Milodin Nov 07 '14 at 11:29
  • +1 for effort; I would put an explanation above that notes this works because your variables are of type `float`, not `int` and that you cleverly paired your operators so you never had an `int`/`int`. – BradleyDotNET Nov 07 '14 at 21:43
  • Thanks, by no means exhaustive and there are omissions in regards to incorrect input etc.. but a reasonable starting point. – Milodin Nov 07 '14 at 21:57
0

This is a general method, which will perform all temperature unit conversions

public static double ConvertTemperatureUnits(TemperatureUnit toConvert, TemperatureUnit from, double value)
    {
        double convertedValue = 0.0;

        if (toConvert == from)
            return value;

        switch (toConvert)
        {
            case TemperatureUnit.FAHRENHEIT:
                {
                    switch (from)
                    {
                        case TemperatureUnit.CELSIUS:
                            convertedValue = (value * 9) / 5 + 32;
                            break;
                        case TemperatureUnit.KELVIN:
                            convertedValue = 1.8 * (value - 273.15) + 32;
                            break;
                    }
                }
                break;
            case TemperatureUnit.KELVIN:
                switch (from)
                {
                    case TemperatureUnit.CELSIUS:
                        convertedValue = value + 273.15;
                        break;
                    case TemperatureUnit.FAHRENHEIT:
                        convertedValue = (value + 459.67) * 5 / 9;
                        break;
                }
                break;
            case TemperatureUnit.CELSIUS:
                switch (from)
                {
                    case TemperatureUnit.KELVIN:
                        convertedValue = value - 273.15;
                        break;
                    case TemperatureUnit.FAHRENHEIT:
                        convertedValue = (value - 32) * 5 / 9;
                        break;
                }
                break;
        }
        return convertedValue;
    }

create TemperatureUnit enum like this

   enum TemperatureUnit
{
    FAHRENHEIT,
    KELVIN,
    CELSIUS
}
Praveen M
  • 443
  • 2
  • 11