-
Notifications
You must be signed in to change notification settings - Fork 391
Temperature times a double #518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Yes, Temperature is tricky, because Edit: Hang on, that's not right either. |
Ah, found it, you can do
|
In either case, multiplication with temperatures is a bit tricky if you don't know the unit you are working with. Thinking in terms of "energy", one would think doubling the Kelvins would be right, but if you are thinking in Celsius (20) and doubling, you expect 40. The reference temperature (zero) is the missing information. |
It make sense why you have done it that way however I don't think it is that tricky. Keeping it in Kelvin you don't have to think about if it is a absolute- or a relative temperature (what you call KelvinDelta [which I can see that you have removed] ). The way I see it: So if I have do: Temperature * double It should return: and not 40°C! An ex. You want to calculate power: Lets say: If you say that: If you say that: Does it make sense? |
It absolutely makes sense and this was in fact the original implementation until this issue came up and the resulting PR: I have myself stumbled on this and I know others have too. It's an easy mistake to make to try to double a temperature in degrees Celsius or Fahrenheit and expect the resulting value to also double, especially if you are not regularly working with temperatures. I think this quote puts it well
So. I see two ways foward:
What do you think? |
Thanks for asking for my opinion. I think you should add support for This could also clean up a lot of the confusion about temperatures An example of the confusion:
This is where you get hanged ;-) If you really want the DegreeCelsius you should say: but then we are back to Another example of the confusion:
To sum up: If you handle temperature like any other unit by doing all the calculation in the SI-unit (Allowing |
Thanks, I value your input. You clearly have a solid grasp on this domain and I agree with almost all you said. This one I find confusing though:
In the current implementation, So, I would expect Hope you can enlighten me on this part, thanks! |
If you look at the Boost units documentation, they do something similar. Here's the output: quantity<absolute<fahrenheit::temperature> > T1p(
32.0*absolute<fahrenheit::temperature>());
quantity<fahrenheit::temperature> T1v(
32.0*fahrenheit::degrees);
quantity<absolute<si::temperature> > T2p(T1p);
quantity<si::temperature> T2v(T1v);
//]
typedef conversion_helper<
quantity<absolute<fahrenheit::temperature> >,
quantity<absolute<si::temperature> > > absolute_conv_type;
typedef conversion_helper<
quantity<fahrenheit::temperature>,
quantity<si::temperature> > relative_conv_type;
std::cout << T1p << std::endl
<< absolute_conv_type::convert(T1p) << std::endl
<< T2p << std::endl
<< T1v << std::endl
<< relative_conv_type::convert(T1v) << std::endl
<< T2v << std::endl
<< std::endl;
return 0; The output is: { 32 } F |
Looking at the Unit system you don't see any Delta Units - Try to find me a SI Delta Unit :-) In the physicists/engineers world this is how it is done: and if you for some reason want to express You can not say If you take This holds true for every single Unit in the unitsystem! Most units have concentric zero points With kelvin and DegreesCelsius: 'with kelvin and Fahrenheit Even your DateTime - DateTime is DateTime!
|
A quick summarizing of my points:
Results in
|
Oh gosh I forgot how badly I dislike C++ syntax, thanks for reminding me 😆 @Mobz87 From a programmer's perspective in science or engineering, this sounds reasonable. From a programmer's perspective working on a weather app and want to find the difference between the warmest point of day and the coldest and express that in Celsius or Fahrenheit - I'm just imagining up a scenario here - this probably gets confusing real quick.
No, it's I think this is an important point when Kelvin is perhaps a foreign concept and you are simply thinking in Fahrenheit and Celsius, because that's what the imagined app does. Scenario: Calculate the degrees of Fahrenheit between warmest and coldest for a dayI speculate most developers would reach for this: var delta = Temperature.FromDegreesFahrenheit(100) - Temperature.FromDegreesFahrenheit(70);
var deltaF = delta.DegreesFahrenheit;
// Alt1: 100F - 70F = 30F = 30F
// Alt2: 311K - 294K = 17K = -429F
// Alt3: 100F - 70F = TemperatureDelta = 30F Now, what is reasonable to expect This is an indication of what is intuitive. It's important. If calculations follow alternative 2 as you propose, this is how I would obtain 30 Fahrenheit: var delta = Temperature.FromDegreesFahrenheit(100) - Temperature.FromDegreesFahrenheit(70);
var deltaF = (Temperature.FromDegreesFahrenheit(0) + delta).DegreesFahrenheit; // 30 Please correct me if there is an easier way to calculate this. This approach seems very counter-intuitive to me at least. I mean, I understand it, but it is not how I would expect to have to code it. TL;DR I'm not arguing to be difficult and am trying to keep an open mind here, I truly just want to make sure we keep the library intuitive for all our users - not only scientists and engineers. I look forward to your reply :-) |
Well averaging on temperatures still work:
because
The only things that doesn't work is: 2°C + 2°C != 4°C (This many programmer will run into) I see that you are caught between doing what is correct (in my world) or whats correct in the minds of most programmers that doesn't study engineering. I still think doing whats correct is the right think to do here. The only thing you need to teach your programmer is: If you want to do this |
I would compare doing but saying: I hope you understand this analogy. If you for your v4.0.0 are up for creating a unit system that are more physicist/engineer friendly I would be happy to help both with guidance and programming. I really like your project(!) but as you might be able to tell, it is important to me that the unit calculation is done correctly :-) |
Might do that to find ratio. Today was 50% warmer than yesterday.
I agree, but I also read hours as Kelvins and TimeSpan as TemperatureDelta in this analog - so I do think that type has some merit.
Is this the correct form or should delta symbol be used here? Not to beat a dead horse, but conversions of temperature difference/delta is a thing: wolframalpha.com, nettam.com, schneider-electric.com How about this:
Something like this: var fahr100 = Temperature.FromDegreesFahrenheit(100);
var fahr50 = Temperature.FromDegreesFahrenheit(50);
var deltaFahr2 = TemperatureDelta.FromDegreesFahrenheit(2); // 2 Δ°F or 1.1 Δ°K
// Temperature and double
Temperature fahr660 = fahr100 * 2.0; // Add
Temperature fahrMinus180 = fahr100 / 2.0; // Add
// Temperature and Temperature
Temperature fahr173k = fahr100 * fahr100; // Weird when not using Kelvins, but is correct
Temperature kelvin1 = fahr100 / fahr100; // Weird when not using Kelvins, but is correct
Temperature fahr660 = fahr100 + fahr100; // Weird when not using Kelvins, but is correct
Temperature fahr0 = fahr100 - fahr100; // Weird when not using Kelvins, but is correct
// Temperature and TemperatureDelta
Temperature fahr200 = fahr100 * deltaFahr2; // Add
Temperature fahr50 = fahr100 / deltaFahr2; // Add
Temperature fahr102 = fahr100 + deltaFahr2; // Keep
Temperature fahr98 = fahr100 - deltaFahr2; // Keep
// Not sure to add/keep or remove these? Might help with discoverability.
Temperature fahr98 = fahr100.Add(-2, TemperatureUnit.Fahrenheit); // Add/remove
Temperature fahr200 = fahr100.Multiply(2, TemperatureUnit.Fahrenheit); // Keep/remove
Temperature fahr50 = fahr100.Divide(2, TemperatureUnit.Fahrenheit); // Keep/remove
// Remove these, weird order. It's like TimeSpan+DateTime.
Temperature fahr120 = deltaFahr20 + fahr100;
Temperature fahr80 = deltaFahr20 - fahr100;
// Other usages
double ratio = fahr100.DegreesFahrenheit / fahr50.DegreesFahrenheit; // 2 |
You are right doing a For people using celsius: For people using Fahrenheit: For people using Kelvin: And if you still want to do this calculation, you can just turn your celsius into a doubles and do the math.
When you look at a unit (°F, °K , °C) you can't tell if it a absolute or relative (delta) by looking at the unit. |
Something like this: var fahr100 = Temperature.FromDegreesFahrenheit(100); // Temperature and double // Temperature and Temperature Temperature kelvin1 = fahr100 / fahr100; // Weird when not using Kelvins, but is correct Temperature fahr660 = fahr100 + fahr100; // Weird when not using Kelvins, but is correct // Temperature and TemperatureDelta
// Not sure to add/keep or remove these? Might help with discoverability. // Remove these, weird order. It's like TimeSpan+DateTime. // Other usages |
I think having the possibility to this is great and helps many people: Temperature = Temperature + DeltaFahrenheit(10);
ex:
Temperature fahr = fahr - deltaFahr(2) I don't hate Delta Δ :-D What I do not like is when I try to do this: Temperature test1;
Temperature test2;
Temperature test3;
test3 = test2 - test1; I get: Cannot implicitly convert type 'UnitsNet.TemperatureDelta' to 'UnitsNet.Temperature' How it is now: how it should be; Now you have to define if your temperature is Delta or not - Delta has nothing to do with the Unit. Delta is something you use to help people understand your equation. ex. If you want to calculate the heating capacity from a radiator:
Here i could shorten my equation to
If I did it this way (wrong way): |
Ah, right. Good point about ensuring correct dimensions in arithmetic, I forgot. So.. if it's not
Agreed, return
Great, agreed.
I kind of agree, but
Ok, on second thought, I agree. It's convenient to suppert both left and right hand, although DateTime does not allow TimeSpan + DateTime. I don't see a problem keeping it and it might help resolve complex arithmetic expressions.
I can see how that is confusing in that context. This will be confusing for either "Kelvin-people" or "Celsius/Fahrenheit-people", and I buy into the point about consistent arithmetic across quantities at the expense of confusing the latter group of people. We just have to provide the tools to easily solve typical Celsius/Fahrenheit scenarios too, andTemperatureDelta arithmetic does that. So. TL;DR Agree on all points, but I suggest removing Update: Sorry, did not mean to ping you guys. But if you still drop by any feedback on this topic is helpful. |
My initial vote is to keep P.S. I might be missing a few points to consider. I'll revisit this issue later after work. :) |
I think keeping it this way is fine. We can add a function for convenience like so.. //usage
var test1 = Temperature.FromDegreesCelsius(20);
var test2 = Temperature.FromDegreesCelsius(50);
Temperature test3 = (test2 - test1).ToTemperature();
Console.WriteLine(test3.Kelvins); //30
//implementation
public static class TemperatureDeltaExtensions
{
public static Temperature ToTemperature(this TemperatureDelta temperatureDelta)
{
return new Temperature(temperatureDelta.Kelvins, TemperatureUnit.Kelvin);
}
} |
I'm convinced by @Mobz87 on this, that we shouldn't introduce a special case for arithmetic with temperatures. It should be calculated with base units, as all other quantities also are - it just happens that delta vs absolute measurment doesn't matter for most other quantities since they share zero point for all their units. However, we should provide convenience for working with temperature differences, since it does add some head scratching. I'm actually thinking of reversing your example @gojanpaolo and do this instead:
In addition to supporting Do you see what I mean? |
I see.. that works too :) |
That sounds perfect! I would love if we had a dynamic way of calculating dimensions!
Maybe |
It's doable to some extent I think, when we move from struct to class we can introduce a generic quantity base type and that type can hold operator overloads between any quantity (I hope) and manipulate the |
I don't have a working solution in mind either . They simply have a class
But I really really like your system for the way you're giving each unit a unique Class name like:
My hope is that with your system we could in the future get both! |
We can do something similar, but it would return a generic quantity just like you wrote it. The only thing I can think of right now for resolving strongly typed arithmetic expressions is creating quantities for all base dimension combinations for 0-3 dimensions. With 7 base units, that's 4^7 => 16384 quantities. Then we would need arithmetic operator overloads between all combinations of quantities. Not even going to bother calculating that one. Suffice to say, this approach doesn't scale :-P |
I would nice to have something that does scale :-D Btw if you still struggle with understanding/believing the MathCad is a Unit calculator - highly trusted and tested, used by engineers and physicists allover the world for many years. For our next unit discussion we could go by the rule: |
Good suggestion. I thought it would be interesting to type in Interestingly, it outputs 10 degrees Celsius as the result :-) I honestly think there is no one right answer here. It depends on context and will be confusing to some no matter what we choose as our default. I still agree that we should use Kelvins as it is a consistent rule we can apply to all our quantities, whereas using deltas for some will maybe add more confusion. But we need to conclude this thread to not go in circle. I propose for |
additional reference: https://physics.stackexchange.com/questions/132720/how-do-you-add-temperatures |
# 4.0.0 Release This PR will serve as the list of items to complete and it will be updated to show the progress before finally merged into `master` when completed. We all have busy schedules, so **if you want to help move this work forward then that is much appreciated!** ## The main theme is to reduce binary size In two years it has grown from 280 kB to 1.4 MB and a lot of it is due to unnecessary syntactic sugar with many method overloads for various number types and nullable types - for every of our 800+ units! It simply adds up to a big total. These items are chosen from #180, trying to include as many of the low hanging fruits as possible, while still keeping the list short and realistic to complete in a reasonably short time - we are all busy in our daily lives. We can always have more major version bumps later than trying to perfect it all now. ## Feature complete before November, merged before mid-December I would like to aim for a "beta" pre-release nuget sometime in October with all the items completed, so we can have some time to test it before releasing the final, stable 4.0.0 version before Christmas holidays. We should have the work items list more or less final before Monday, October 8th. ## Changes #### Added - [x] UnitSystem with a different meaning, now defines the base units for a unit system (#524) #### Removed - [x] Replace netstandard1.0 target with netstandard2.0, to avoid the extra dependencies (#477) - [x] Remove code marked as `[Obsolete]`, such as `VolumeUnit.Teaspoon` (#490) - [x] Remove nullable `From` factory methods (#483) - [x] Remove extension methods on _nullable_ number types (#483) - [x] Remove all number extension methods (#497) - [x] Remove `Length2d`, replaced by `Area` (#501) - [x] Remove static methods on `UnitSystem`, should use `UnitSystem.Default` instead (#496) - [x] Remove unit parameter from `ToString()` methods (#546) #### Changed - [x] Throw exception on NaN values in static constructor methods, like `FromMeters()` (#502, see #176 (comment)) - [x] Throw if unit was not specified when constructing quantities, (#499 - #389 (comment)) - [x] Stricter parsing (#343 and #180 (comment)) - [x] Remove unit parameter from `ToString()` methods (#546) - [x] Change Temperature arithmetic back to use base unit Kelvin (#550, see #518) #### Renamed - [x] Correct SingularName for some Flow unit definitions (#494, see #360) - [x] Split/rename UnitSystem into UnitParser, GlobalConfiguration, UnitAbbreviationsCache (#511) #### Fixed - [x] Search for any TODO comments in the code to address, remove comment and either fix or create issue (5d24432) - [x] Update README with v4 changes #498 - [x] Do not try/catch in UnitConverter.Try-methods (#506) - [x] Do not try/catch in `Length.TryParse()` and for other quantities (#507) - [x] Add/update changelog in wiki for v4 with some summary copied from this issue, some v3 to v4 migration instructions and briefly explain why some stuff were removed ## Milestones - [x] Finalize work items list (Monday, October 8) - [x] Release 4.0.0-beta1, feature complete (Wednesday, October 31) - [ ] ~Show release notes and upgrade guide when upgrading to 4.x nuget, if possible~ - [x] Release 4.0.0 (Monday, December 17)
I am closing this issue since v4 is now released and we decided to stay with the old behavior until someone can present convincing evidence that it will be an improvement for the majority of our userbase to change this behavior. It will be non-intuitive to some part of the userbase regardless, and at this point we don't know if it is the majority that is confused or the minority. Please reopen if you want to champion this and gather the information we need to decide. |
Is there a specific reason that I cant do:
Temperature * double
even though I can do it with every other unit?
The text was updated successfully, but these errors were encountered: