sharkdp / numbat

A statically typed programming language for scientific computations with first class support for physical dimensions and units
https://numbat.dev
Apache License 2.0
1.12k stars 45 forks source link

Add support for Celsius_to_Fahrenheit and Fahrenheit_to_Celsius scalar functions #184

Open archisman-panigrahi opened 11 months ago

archisman-panigrahi commented 11 months ago

I totally agree (with https://github.com/sharkdp/insect/issues/68) that Celsius and Fahrenheit are problematic units to work with, and it's best not to support any arithmetic with them.

However, Celsius and Fahrenheit are among the most commonly converted units (to be frank, after moving to the US, this is the most frequent unit conversion I mentally do everyday, using the (approximate) formula c ≈ (f-30)/2)


I propose we include two functions (whose input and output are both scalar), Celsius_to_Fahrenheit and Fahrenheit_to_Celsius, which will work like the following.

>>> Celsius_to_Fahrenheit(c)
    #Alternative 1, print the value of (32 + 9*c/5)
    #Alternative 2, print the string "c°C = (32 + 9*c/5)°F"

>>> Fahrenheit_to_Celsius(f)
    #Alternative 1, print the value of 5*(f-32)/9
    #Alternative 2, print the string "f°F = 5*(f-32)/9 °C"
sharkdp commented 11 months ago

I totally agree (with sharkdp/insect#68) that Celsius and Fahrenheit are problematic units to work with, and it's best not to support any arithmetic with them.

Maybe we should revisit this and add (proper, limited) support for dealing with °C and °F directly.

I propose we include two functions (whose input and output are both scalar), Celsius_to_Fahrenheit and Fahrenheit_to_Celsius, which will work like the following.

Note that you can do this today. Just add the following to your init.nbt file:

fn celsius_to_fahrenheit(t_c: Scalar) -> String =
  "{t_c}°C = {32 + 9 t_c/5}°F"

fn fahrenheit_to_celsius(t_f: Scalar) -> String =
  "{t_f}°F = {5 × (t_f-32)/9}°C"

(you might want to add rounding)

Try it here.

Also, did you notice that we have to_fahrenheit, from_fahrenheit, to_celsius, and from_celsius already?

sharkdp commented 11 months ago

Another thing we can do right now is the following:

dimension TCelsius
unit °C: TCelsius

dimension TFahrenheit
unit °F: TFahrenheit

fn to_F(temp: TCelsius) -> TFahrenheit = (32 + 9 × (temp / °C) / 5) °F
fn to_C(temp: TFahrenheit) -> TCelsius = (5 × (temp / °F - 32) / 9) °C

And then use it like so:

>>> 30°C // to_F

      = 86 °F    [TemperatureFahrenheit]

Try it here

archisman-panigrahi commented 11 months ago

I like this (i.e. fn celsius_to_fahrenheit approach) more than the second one.

If we add the units Celsius and Fahrenheit, then numbat will also be able to add, subtract and divide them, all of which are unphysical operations.

Someone may try to evaluate boltzmann_constant * 30°C -> eV, and supporting such operations may create many problems.

Note that you can do this today. Just add the following to your init.nbt file:

While I know how to do this, I am suggesting we add these functions to the default interface, so that Linux users looking for an unit converter will not have to write code to do these conversions, and we can recommend numbat to them.

triallax commented 7 months ago

@sharkdp I like your suggestion.

If we add the units Celsius and Fahrenheit, then numbat will also be able to add, subtract and divide them, all of which are unphysical operations.

That shouldn't be a problem if each has its own dimension, right? Because then you can't combine the different temperature units without explicitly converting them.

sharkdp commented 6 months ago

If we add the units Celsius and Fahrenheit, then numbat will also be able to add, subtract and divide them, all of which are unphysical operations.

That shouldn't be a problem if each has its own dimension, right? Because then you can't combine the different temperature units without explicitly converting them.

No, @archisman-panigrahi is right. It is still a problem. Adding two values in °C usually doesn't make any sense (unless one of them is an absolute value and the other one a relative value). It's kind of similar to DateTimes and durations.

I think we probably need to add proper support in the language for units with additive offsets. A first step would be to add support for units that you can't do anything with... except convert to and from.