Laden...

Temperatur Umrechner

Erstellt von Joetempes vor 7 Jahren Letzter Beitrag vor 7 Jahren 11.112 Views
Joetempes Themenstarter:in
888 Beiträge seit 2007
vor 7 Jahren
Temperatur Umrechner

Beschreibung:

Ein Temperatur-Umrechner für Celsius, Fahrenheit und Kelvin in allen Varianten.


namespace Tools
{
    /// <summary>
    /// Helfer für Umwandlung von Temperatureinheiten
    /// </summary>
    public static class TemperatureHelper
    {
        /// <summary>
        /// Konvertiert einen Celsius-Wert in einen Fahrenheit-Wert
        /// </summary>
        /// <param name="celsius">Celsius-Wert</param>
        /// <returns>Fahrenheit-Wert</returns>
        public static double ConvertCelsiusToFahrenheit( double celsius )
        {
            return ( ( 9.0 / 5.0 ) * celsius ) + 32;
        }

        /// <summary>
        /// Konvertiert einen Fahrenheit-Wert in einen Celsius-Wert
        /// </summary>
        /// <param name="fahrenheit">Fahrenheit-Wert</param>
        /// <returns>Celsius-Wert</returns>
        public static double ConvertFahrenheitToCelsius( double fahrenheit )
        {
            return ( 5.0 / 9.0 ) * ( fahrenheit - 32 );
        }

        /// <summary>
        /// Konvertiert einen Celcius-Wert in einen Kelvin-Wert
        /// </summary>
        /// <param name="celsius">Celcius-Wert</param>
        /// <returns>Kelvin-Wert</returns>
        public static double ConvertCelciusToKelvin( double celsius )
        {
            return celsius + 273.15;
        }

        /// <summary>
        /// Konvertiert einen Kelvin-Wert in einen Celcius-Wert
        /// </summary>
        /// <param name="kelvin">Kelvin-Wert</param>
        /// <returns>Celcius-Wert</returns>
        public static double ConvertKelvinToCelcius( double kelvin )
        {
            return kelvin - 273.15;
        }

        /// <summary>
        /// Konvertiert einen Fahrenheit-Wert in einen Kelvin-Wert
        /// </summary>
        /// <param name="fahrenheit">Fahrenheit-Wert</param>
        /// <returns>Kelvin-Wert</returns>
        public static double ConvertFahrenheitToKelvin( double fahrenheit )
        {
            return ( fahrenheit + 459.67 ) * 5.0 / 9.0;
        }

        /// <summary>
        /// Konvertiert einen Kelvin-Wert in einen Fahrenheit-Wert
        /// </summary>
        /// <param name="kelvin">Kelvin-Wert</param>
        /// <returns>Fahrenheit-Wert</returns>
        public static double ConvertKelvinToFahrenheit( double kelvin )
        {
            return kelvin * 9.0 / 5.0 - 459.67;
        }
    }
}

Schlagwörter: Temperatur, Umrechner, Celsius, Fahrenheit, Kelvin

6.911 Beiträge seit 2009
vor 7 Jahren

Hallo Joetempes,

danke. Als Erweiterungsmethoden wäre es (oftmals) noch praktischer. Auch könnte eine Prüfung auf ungültige Zustände (< 0K) eingebaut werden -- vllt. per optionalen boolschen Argument, denn die Prüfung kann nicht immer gewünscht sein.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

W
955 Beiträge seit 2010
vor 7 Jahren

Noch besser wäre ein struct der das intern vllt als Kelvin hält und dann entsprechende Fabrikmethoden / Ausgabemethoden bereithält. Dann könnte man noch Operatoren definieren, IEquatable/IComparable implementieren und dadurch einen richtigen Datentypen erstellen.

Joetempes Themenstarter:in
888 Beiträge seit 2007
vor 7 Jahren

Danke für die Hinweise, aber ich ändere daran nichts mehr.
Was auch noch, der Vollständigkeit halber, ergänzt werden könnte, sind weitere bekannte Temperaturskalen wie: Rankine, Delisle, Réaumur, Newton und Rømer.

1.040 Beiträge seit 2007
vor 7 Jahren

Moin,

wenn du die Klasse produktiv einsetzt, dann musst du auf jeden Fall nochmal ran:

  • in der Funktion ConvertFahrenheitToKelvin ergibt 5 / 9 IMMER 0 (int-Berechnung!), dadurch ist das Ergebnis falsch
  • in den Funktionen ConvertFahrenheitToKelvin und ConvertKelvinToFahrenheit 273.15 statt 273 nutzen, sonst ist das Ergebnis falsch

Weiterhin könnte man noch folgende Punkte ändern:

  • statt immer 9.0 / 5.0 zu rechnen, einfach 1.8 nutzen
  • statt ( 5.0 / 9.0 ) * x zu rechnen, einfach x / 1.8
  • Teile einer Berechnung durch Funktionen ersetzen, z.B.
public static double ConvertFahrenheitToKelvin( double fahrenheit )
{
    return ( 5 / 9 * ( fahrenheit - 32 ) + 273 );
}
public static double ConvertFahrenheitToKelvin( double fahrenheit )
{
    return ConvertCelciusToKelvin(ConvertFahrenheitToCelsius(fahrenheit));
}

oder

public static double ConvertKelvinToFahrenheit( double kelvin )
{
    return ( ( ( kelvin - 273 ) * 9 / 5 ) + 32 );
}
public static double ConvertKelvinToFahrenheit(double kelvin)
{
    return ConvertCelsiusToFahrenheit(ConvertKelvinToCelcius(kelvin));
}

=)

3.003 Beiträge seit 2006
vor 7 Jahren

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 7 Jahren

Nun ja, so ganz sauber ist die noch nicht ...

am meisten Kopfschütteln bekomme ich bei

On the advice of someone over at Code Project, I removed the arithmetic operator overloads in favor of a Change method. This method returns the temperature change between two values according to the measurement unit of your choosing.

Da wird jetzt ein double zurückgeliefert.

Wie brüllte mein Lehrer in der Grundschule, wenn auf die Frage "5 Äpfel - 3 Äpfel sind?" eine lapidares "Zwei" zurückkam: "Was zwei? Hunde, Katzen, Schweine?". Und er hatte recht (nicht mit der Lautstärke).

Eine wirklich saubere Lösung würde analog dem DateTime folgen und neben Temperature würde es auch noch ein TemperatureSpan geben. Eine absolute Temperatur hat als MinValue 0 Kelvin, die Differenz zwischen 5000 Kelvin und 0 Kelvin sind aber -5000 Kelvin, die dann korrekt als TemperatureSpan zurückgegeben werden sollten.

Mal sehen ob ich Zeit finde das zusammenzustellen - würde auch zu meinem aktuellen Projekt passen.

Joetempes Themenstarter:in
888 Beiträge seit 2007
vor 7 Jahren

Hallo Leute,

danke für Eure Hinweise, Rechenfehler gehen natürlich gar nicht!

Die Kelvin <-> Fahrenheit Methoden habe ich nochmal angepasst.
Die Ergebnisse stimmen jetzt mit dem Google Temperatur Umrechner überein.

Für meine Zwecke genügt das....

3.003 Beiträge seit 2006
vor 7 Jahren

Eine wirklich saubere Lösung würde analog dem DateTime folgen und neben Temperature würde es auch noch ein TemperatureSpan geben.

Das wäre physikalisch falsch. Kelvin ist (auch) eine Temperaturdifferenz-Angabe, ohne Angabe der Referenz gilt der absolute Nullpunkt als Referenz und die Angabe dann als Temperaturangabe. Insofern besteht ein wesentlicher Unterschied zum Datum, und die Temperatur sollte auch nicht so abgebildet werden, wie von dir vorgeschlagen.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 7 Jahren

Wir könnten uns aber schon drauf einigen, dass 10°C wärmer und 10°C gemessene Temperatur etwas völlig anderes sind, genau wie 10h später und 10:00 Uhr.

Meines Wissens stellt jeder DateTime-Wert auch eine Differenz dar zu einem festgelegten Bezugspunkt (also wie bei der Temperaturangabe in Kelvin), nur dass es eben unter 0 Kelvin keine Temperatur mehr - physikalisch gesehen - gibt.

Ich kann mich natürlich auch irren.

3.003 Beiträge seit 2006
vor 7 Jahren

Naja, dein Irrtum besteht darin, dass es auch thermodynamischer Sicht keine Temperatur gibt, sondern nur Temperaturunterschiede. Und nein, 10K und 10K sind dasselbe.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 7 Jahren

Wie würdest du das denn umsetzen?

P
1.090 Beiträge seit 2011
vor 7 Jahren

Ich muss grade an einen Witz denken.

Sitzen ein Astrophysiker, eine Physiker und ein Mathematiker in einem Zug, in England und sind auf dem Weg zu einer Konferenz. Da entdeckt der Astrophysiker, durch das Fenster ein schwarzes Scharf. Und sagt: Schaut mal, in England gibt es schwarze Scharfe.
Sagt der Physiker: „Das ist so nicht korrekt. In England gibt es mindestens ein schwarzes Scharf.“
Sagt der Mathematiker: „Das ist so auch nicht korrekt. In England gibt es mindestens ein Scharf was von einer Seite schwarz ist.“

@LaTino
Also meines Wissens ist es so, das auch in der Thermodynamik festgelegt ist, das bei 273,16 K der Tripelpunkt des Wassers ist. (Für Astrophysiker der Gefrierpunkt 😉 ).
Wobei es dann schon einen unterschied macht ob ich eine Temperatur von -10K habe oder eine Temperatur Differenz von -10K.
Was natürlich gegeben ist, ist das eine Temperatur Differenz von 10K einer Temperatur Differenz von 10°C entspricht. Aber eine Temperatur von 273,16 K entspricht einer Temperatur von 0,01°C.

@Ich möchte jetzt aber nicht ausschließen, das es Bereiche in der Thermodynamik gibt, bei denen man davon Ausgeht, das man bei 10K von eine Temperatur Differenz spricht. eV wird ja auch in der Teilchenphysik als Masse verwendet (E=mc^2).

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

3.003 Beiträge seit 2006
vor 7 Jahren

Der Witz trifft es (leider). Sorry für meinen Krümelkackerismus 😉.

@Palin, K wird nur implizit für absolute Temperaturangaben benutzt. Die Festlegung auf den Tripelpunkt wurde getroffen, um 1K = 1°C zu haben, was ja auch durchaus Sinn ergibt. Mein letzter Stand war, dass man dafür einen Ersatz sucht, irgendetwas, das auf eine Naturkonstante zurückzuführen ist (wie bei anderen Einheiten auch). 10K ohne Referenzangabe bezieht sich immer auf 10K(0), mit Tripelpunkt 276.16K(0). "10 Grad wärmer" ist sprachlich völlig in Ordnung, formal aber a) ohne Bezugspunkt (wärmer als was?) und b) ohne Einheit (entweder "Kelvin" ohne Grad oder "Grad Celsius/Fahrenheit/Bogenmaß/Oechsle"). 10 Grad wärmer (als gestern, wo es 0 Grad Celsius hatte) => 10K(273.15) bzw einfach 273.15K + 10K, weil, wie erwähnt, dankenswerterweise 1°C = 1K.

Abbilden würde ich das schlicht als immutable struct mit Erweiterungsmethoden oder statischen Methoden. Der Bezugspunkt kann dabei entfallen, indem man einfach immer den absoluten Nullpunkt als Bezug nimmt und für Umrechnungen dann eben Temp.FromCelsius(0.01).ToFahrenheit(); Du hast so keine bloße Erweiterung für double - was blöd wäre. Abbilden würde der struct dabei also immer eine Temperaturdifferenz. Für den Benutzer macht das aber keinen Unterschied, wie es auch im täglichen Leben keinen Unterschied macht, ob wir nun sagen "Oberflächentemperatur von Titan ist 94K" oder "94K mehr als der absolute Nullpunkt" oder "-179 °C". Ist alles verdammt kalt, bzw verdammt viel kälter als die Füße meiner Frau 😃.

LaTino
(Möglicherweise erinnere ich mich auch ganz falsch, und ein Therodynamiker würde angesichts meines Postings die Hände überm Kopf zusammenschlagen. Will ich nicht ausschließen^^)

EDIT: irgendwie so oder ähnlich.


    public struct Temperature
    {
        private const double ABSOLUTE_NULL_CELSIUS = 273.15;
        private const double ABSOLUTE_NULL_FAHRENHEIT = 459.67;
        private const double KELVIN_FAHRENHEIT_CONVERSION = 1.8;
        private const double COMPARISON_DELTA = 0.000001;

        private Temperature(double fromKelvin)
        {
            Kelvin = fromKelvin;
        }

        public static Temperature FromKelvin(double absoluteKelvin) => new Temperature(absoluteKelvin);
        public static Temperature FromCelsius(double absoluteCelsius) => new Temperature(ABSOLUTE_NULL_CELSIUS + absoluteCelsius);
        public static Temperature FromFahrenheit(double absoluteFahrenheit) => new Temperature((ABSOLUTE_NULL_FAHRENHEIT + absoluteFahrenheit) / KELVIN_FAHRENHEIT_CONVERSION);

        public double Kelvin { get; }
        public double Celsius => Kelvin - ABSOLUTE_NULL_CELSIUS;
        public double Fahrenheit => Kelvin*KELVIN_FAHRENHEIT_CONVERSION - ABSOLUTE_NULL_FAHRENHEIT;

        #region Equality Members
        public bool Equals(Temperature other) => Kelvin.Equals(other.Kelvin) || Math.Abs(Kelvin - other.Kelvin) < COMPARISON_DELTA;
        public override bool Equals(object obj) => !ReferenceEquals(null, obj) && (obj is Temperature && Equals((Temperature) obj));
        public override int GetHashCode() => Kelvin.GetHashCode();
        #endregion

        #region operator overloads
        public static Temperature operator +(Temperature leftSummand, Temperature rightSummand) => FromKelvin(leftSummand.Kelvin + rightSummand.Kelvin);
        public static Temperature operator -(Temperature minuend, Temperature subtrahend) => FromKelvin(minuend.Kelvin - subtrahend.Kelvin);
        public static bool operator ==(Temperature leftOperator, Temperature rightOperator) => leftOperator.Equals(rightOperator);
        public static bool operator !=(Temperature leftOperator, Temperature rightOperator) => !(leftOperator == rightOperator);

        #region convenience operator overloads with double
        public static Temperature operator +(Temperature leftSummand, double rightSummand) => FromKelvin(leftSummand.Kelvin + rightSummand);
        public static Temperature operator +(double leftSummand, Temperature rightSummand) => FromKelvin(leftSummand + rightSummand.Kelvin);
        public static Temperature operator -(Temperature minuend, double subtrahend) => FromKelvin(minuend.Kelvin - subtrahend);
        public static Temperature operator -(double minuend, Temperature subtrahend) => FromKelvin(minuend - subtrahend.Kelvin);

        public static bool operator ==(Temperature leftOperator, double rightOperator) => Math.Abs(leftOperator.Kelvin - rightOperator) < COMPARISON_DELTA;
        public static bool operator !=(Temperature leftOperator, double rightOperator) => !(leftOperator == rightOperator);
        public static bool operator ==(double  leftOperator, Temperature rightOperator) => Math.Abs(leftOperator - rightOperator.Kelvin) < COMPARISON_DELTA;
        public static bool operator !=(double leftOperator, Temperature rightOperator) => !(leftOperator == rightOperator);
        #endregion
        #endregion
    }

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 7 Jahren

Aha


var temp1 = Temperature.FromCelsius( 20 );
var temp2 = Temperature.FromCelsius( 5 );
var tempResult = temp1 - temp2;

Console.WriteLine( "{0}°C - {1}°C = {2}°C", temp1.Celsius, temp2.Celsius, tempResult.Celsius );

ergibt


20°C - 5°C = -258,15°C

Da beleibe ich doch lieber bei meiner Variante 😁

3.003 Beiträge seit 2006
vor 7 Jahren

~~Du meinst, du nimmst Kelvin, schreibst Celsius dran und dann stimmt es nicht?

Na, dann.~~ Hö?^^

EDIT: ah, da ist er ja, der Denkfehler. Du ziehst 5 Grad Celsius ab, also 278K. Du wolltest aber 5K abziehen. Temperaturunterschiede sind IMMER K. Ich sehe aber, dass das missverständlich sein kann, wenn man "minus 5°C" gleichsetzt mit "minus 5K".

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 7 Jahren

Nein, ich nehme Temperature.FromCelsius (also einen Celsius Wert) subtrahiere die beiden und lasse mir das Ergebnis als Celsius ausgeben.

Also


delta t = t1(0K) - t2(0K)

falsch ist


t(0K) = t1(0K) - t2(0K)

3.003 Beiträge seit 2006
vor 7 Jahren

So herum sind es 15K Temperaturunterschied, also (in absoluten Grad Celsius) -258,15°C. Ist doch richtig? oO

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 7 Jahren

Eben es sind 15K Temperaturunterschied (delta t) den du aber wieder als Temperatur (t(0K)) zurückgibst.

Darum würde ich als Ergebnis nicht Temperature (t(0K)) sondern ein TemperatureSpan (delta t) zurückliefern. Denn genau das ist es. Der Bezugspunkt zu 0K geht bei der Subtraktion flöten.

Und dann kann man auch wieder sinnvoll weiterrechnen


delta t = t1(0K) - t2(0K)
t4(0K) = t3(0K) + delta t

3.003 Beiträge seit 2006
vor 7 Jahren

public double Din13011Celsius => Kelvin;

Fix für dich 😉. Temperaturunterschiede sollen nicht in °C angegeben werden, dürfen nach DIN 1301-1 aber (war mir auch neu). Angabe Temperaturunterschied einfach als "Grad" ist nicht erlaubt, forciert wird, wenigstens in Chemie und Physik, einfach K.

(was mich so verwirrt, ist, dass du ganz normal Grad Celsius als Temperaturunterschied auffasst. Rein sprachlich wäre für mich eine Temperaturangabe mit "Grad Celsius", und eine Temperaturunterschied-Angabe mit "Grad" (oder "Kelvin", wenn ich im wiss. Kontext bin). Hängt im gesprochenen Wort "Celsius" dran, würde ich glaub ich nicht drauf kommen, dass ein Unterschied gemeint ist.)

Wie sich ganz oben schon angedeutet hat, würden wir, wenn uns nur über Temperaturen unterhielten, wohl gnadenlos aneinander vorbei reden 😉.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 7 Jahren

Ähm dein struct hat intern den Wert als Kelvin vorliegen und ich lese den mithilfe deines Struct über die Eigenschaft Celsius raus.

Wenn das verboten ist, dann sollte da eine Exception kommen.

Und wenn man wissen muss, ob dieser Temperature Wert eine Differenz oder basierend zu 0K ist, dann ist so ein Gebilde nicht wirklich hilfreich.

3.003 Beiträge seit 2006
vor 7 Jahren

*seufz* Du möchtest gern folgende Unterscheidung treffen:

Temperatur: °C = K - 273,15.
Temperaturunterschied: °C = K

Und weil das unterschiedliche Berechnungen sind, brauchst du zwei Klassen. Damit unterläufst du aber die eigentliche Verwendung, wie ich oben schon erklärt habe. EDIT: abgesehen davon wird es niemanden abhalten, versehentlich aus einem Temperaturunterschied eine absolute Temperatur zu machen - selbes Problem, nur andersrum.

Ich sehe das so:

Temperatur: °C = K - 273,15
Temperaturunterschied: K

Und schon entfällt die Notwendigkeit von zwei Klassen.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 7 Jahren

Wenn man die Anwendung aber intuitiv halten möchte, dann macht man einfach


public struct Temperature
{
    private const double ABSOLUTE_NULL_CELSIUS = 273.15;
    private const double ABSOLUTE_NULL_FAHRENHEIT = 459.67;
    private const double KELVIN_FAHRENHEIT_CONVERSION = 1.8;
    private const double COMPARISON_DELTA = 0.000001;

    private Temperature( double fromKelvin )
    {
        Kelvin = fromKelvin;
    }

    public static Temperature FromKelvin( double absoluteKelvin ) => new Temperature( absoluteKelvin );
    public static Temperature FromCelsius( double absoluteCelsius ) => new Temperature( ABSOLUTE_NULL_CELSIUS + absoluteCelsius );
    public static Temperature FromFahrenheit( double absoluteFahrenheit ) => new Temperature( ( ABSOLUTE_NULL_FAHRENHEIT + absoluteFahrenheit ) / KELVIN_FAHRENHEIT_CONVERSION );

    public double Kelvin { get; }
    public double Celsius => Kelvin - ABSOLUTE_NULL_CELSIUS;
    public double Fahrenheit => Kelvin * KELVIN_FAHRENHEIT_CONVERSION - ABSOLUTE_NULL_FAHRENHEIT;

    #region Equality Members
    public bool Equals( Temperature other ) => Kelvin.Equals( other.Kelvin ) || Math.Abs( Kelvin - other.Kelvin ) < COMPARISON_DELTA;
    public override bool Equals( object obj ) => !ReferenceEquals( null, obj ) && ( obj is Temperature && Equals( (Temperature) obj ) );
    public override int GetHashCode() => Kelvin.GetHashCode( );
    #endregion

    #region operator overloads
    public static Temperature operator +( Temperature leftSummand, TemperatureDelta rightSummand ) => FromKelvin( leftSummand.Kelvin + rightSummand.Kelvin );
    public static Temperature operator +( TemperatureDelta leftSummand, Temperature rightSummand ) => FromKelvin( leftSummand.Kelvin + rightSummand.Kelvin );
    public static Temperature operator -( Temperature minuend, TemperatureDelta subtrahend ) => FromKelvin( minuend.Kelvin - subtrahend.Kelvin );
    public static TemperatureDelta operator -( Temperature minuend, Temperature subtrahend ) => TemperatureDelta.FromKelvin( minuend.Kelvin - subtrahend.Kelvin );
    public static bool operator ==( Temperature leftOperator, Temperature rightOperator ) => leftOperator.Equals( rightOperator );
    public static bool operator !=( Temperature leftOperator, Temperature rightOperator ) => !( leftOperator == rightOperator );
    #endregion
}

public struct TemperatureDelta
{
    private const double KELVIN_PER_CELSIUS = 1.0;
    private const double KELVIN_PER_FAHRENHEIT = 5.0 / 9.0;
    private const double COMPARISON_DELTA = 0.000001;

    private TemperatureDelta( double fromKelvin )
    {
        Kelvin = fromKelvin;
    }

    public static TemperatureDelta FromKelvin( double deltaKelvin ) => new TemperatureDelta( deltaKelvin );
    public static TemperatureDelta FromCelsius( double deltaCelsius ) => new TemperatureDelta( KELVIN_PER_CELSIUS * deltaCelsius );
    public static TemperatureDelta FromFahrenheit( double deltaFahrenheit ) => new TemperatureDelta( KELVIN_PER_FAHRENHEIT * deltaFahrenheit );

    public double Kelvin { get; }
    public double Celsius => Kelvin / KELVIN_PER_CELSIUS;
    public double Fahrenheit => Kelvin / KELVIN_PER_FAHRENHEIT;

    #region Equality Members
    public bool Equals( TemperatureDelta other ) => Kelvin.Equals( other.Kelvin ) || Math.Abs( Kelvin - other.Kelvin ) < COMPARISON_DELTA;
    public override bool Equals( object obj ) => !ReferenceEquals( null, obj ) && ( obj is TemperatureDelta && Equals( (TemperatureDelta) obj ) );
    public override int GetHashCode() => Kelvin.GetHashCode( );
    #endregion

    #region operator overloads
    public static TemperatureDelta operator +( TemperatureDelta leftSummand, TemperatureDelta rightSummand ) => FromKelvin( leftSummand.Kelvin + rightSummand.Kelvin );
    public static TemperatureDelta operator -( TemperatureDelta minuend, TemperatureDelta subtrahend ) => FromKelvin( minuend.Kelvin - subtrahend.Kelvin );
    public static bool operator ==( TemperatureDelta leftOperator, TemperatureDelta rightOperator ) => leftOperator.Equals( rightOperator );
    public static bool operator !=( TemperatureDelta leftOperator, TemperatureDelta rightOperator ) => !( leftOperator == rightOperator );
    #endregion
}

und schon geht


var temp1 = Temperature.FromCelsius( 20 );
var temp2 = Temperature.FromCelsius( 5 );
var tempResult = temp1 - temp2;

Console.WriteLine( "{0}K(0K) - {1}K(0K) = {2}K(delta)", temp1.Kelvin, temp2.Kelvin, tempResult.Kelvin );
Console.WriteLine( "{0}°C(0°C) - {1}°C(0°C) = {2}°C(delta)", temp1.Celsius, temp2.Celsius, tempResult.Celsius );
Console.WriteLine( "{0}°F(0°F) - {1}°F(0°F) = {2}°F(delta)", temp1.Fahrenheit, temp2.Fahrenheit, tempResult.Fahrenheit );

und liefert (wie ich es wenigstens erwarten würde)


293,15K(0K) - 278,15K(0K) = 15K(delta)
20°C(0°C) - 5°C(0°C) = 15°C(delta)
67,9999999999999°F(0°F) - 40,9999999999999°F(0°F) = 27°F(delta)

Schon braucht man dem Verwender dieses Gebildes keinen thermodynamischen Vortrag zu halten, sondern lässt den das einfach benutzen.

Und wie schon gesagt: Wie bei DateTime und TimeSpan

UPDATE 2 Fehler im Code korrigiert

3.003 Beiträge seit 2006
vor 7 Jahren

Assert.AreNotEqual(Temperature.FromKelvin(tempResult.Kelvin), temperature.FromCelsius(tempResult.Celsius));

Ohne thermodynamischen Vortrag erklärst du aber auch nicht, wieso das fehlschlägt. (Und wieso 68-41 = 8.3 sind). Du verlagerst das Problem nur - aber hier stehen jetzt beide Varianten, die beide korrekt benutzt werden möchten, ich denke, dabei können wir es belassen 😃.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 7 Jahren

Also ich hatte in dem Code einen Umrechnungsfehler von dir übernommen und selber noch einen eingebaut.

Beides korrgiert.

Und wie bei DateTime und TimeSpan kann ich aus einer Zeitspanne nicht einfach ein Datum machen.

Gut ich kann, aber dann muss ich mich auch nicht wundern, wenn ich bei der gleichen Zeitspanne mit unterschiedlichen Bezugspunkten unterschiedliche Werte herausbekomme.

Genau das macht man aber, wenn man


TemperatureDelta tempResult = TemperatureDelta.FromKelvin( 15 );
var tempZeroKelvinBased = Temperature.FromKelvin(tempResult.Kelvin);
var tempZeroCelsiusBased = Temperature.FromCelsius(tempResult.Celsius)

Da braucht man keine Thermodynamik.

Zehn Stunden nach Christi Geburt ist halt was anders als Zehn Stunden nach dem Urknall

16.807 Beiträge seit 2008
vor 7 Jahren

Da es sich hier nicht mehr um Snippets handelt, habe ich das Thema in Reviews verschoben.
Das Resultat hieraus kann dann gerne wieder in Code Snippets gepostet werden.

3.003 Beiträge seit 2006
vor 7 Jahren

Ist doch dasselbe in grün, nur dass man die Probleme auf die andere Seite schiebt.

Man kann davon ausgehen, dass der Benutzer Temperaturunterschiede nur in K handelt, oder man kann davon ausgehen, dass der Benutzer, wenn er Temperaturunterschiede hat, weiß, wie er daraus vernünftig eine Temperatur bastelt. Ich find' die erste intuitiver, du offenbar die zweite 😃. Jedesmal, wenn einer das "falsch" benutzt, kommen wir in Erklärungsnöte.

Bei dir ist ein Grad Celsius mal ein Kelvin, mal 274 Kelvin. Dafür hat man die Zusatzangabe, ob es nun ein Kelvin oder 274 sind, und kann/muss entsprechend handeln. Wenn nicht, muss man sich auch nicht wundern.

Bei mir ist ein Grad Celsius immer 274 Kelvin. Temperaturunterschiede sind immer Kelvin, und nur Kelvin. Man weiss also immer, was man hat, dafür kann man nicht einfach "x Grad Celsius" irgendwo abziehen oder draufrechnen. Wenn man's doch macht, muss man sich auch nicht wundern.

Wie ich schrieb: resultiert beides aus unterschiedlichem Verständnis von Temperatur. Für mich ist Temperatur eine Einheit wie Zeit oder Entfernung. Für dich wie Datum oder Ort. Zeit ist dann die Differenz zwischen zwei Daten, und Entfernung die zwischen zwei Orten.

(Vergessene Klammern korrigiert: Kinder, nie ohne unittest!)

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 7 Jahren

Das mag an meiner schlichten Denkensweise liegen oder der meiner Kunden. Die wollen z.B. die Temperaturen in °C erfassen und in der Auswertung möchten sie die Werte und Veränderungen zum vorherigen Wert auch in °C sehen.*

Ist thermodynamisch bestimmt eine Katastrophe, aber so sind wir schlichten Gemüter halt und
schließlich zahlt der Kunde die Zeche, also bekommt er das was er haben will, auch wenn es falsch ist. Glücklich ist er und das zählt 😁

* Ich vergaß die internationalen Kunden, die teilweise exakt das Gleiche nur in °F erfassen/sehen wollen

3.003 Beiträge seit 2006
vor 7 Jahren

Ach, komm schon, kein Grund für Sarkasmus, ich hab nirgends behauptet, dass deine Sichtweise falsch ist (physikalisch falsch waren meine Worte, und das ist ja auch so. Aber ich verbiete ja auch niemandem, "mach det Fenster zu, die Kälte kommt rin!" zu sagen 😉 ).

Temperaturunterschiede in °C gehen mit beiden Modellen natürlich. Die Anwendung und Stolperfallen variieren halt. Und wenn man ausschließlich mit Celsius arbeitet, dann würde ich wärmstens empfehlen, das ganze struct wegzulassen: Umrechnung war die einzige Motivation.

var result = Temperature.FromCelsius(Temperature.FromFahrenheit(100).Celsius - Temperature.FromKelvin(280).Celsius).Celsius;

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)