ruby-units
ruby-units copied to clipboard
Question/discuss: simplification of units after division
We have been using the RubyUnits gem for quite some time now in our application to perform calculations with units. Sometimes it happens we divide two RubyUnit objects with the same units. In this case the unit information is lost, e.g. Unit.new('10 kg') / Unit.new('5 kg')
equals 2
instead of 2 kg/kg
. I think this is technically correct, but sometimes it would be preferable to keep the unit information to better understand the data you're looking at.
Real world example from our application: we calculate the amount of CO2-emission normalised by something, e.g. the amount of produced product. Both could be measured in weight in kilograms, for example the amount of CO2 per kg produced paper. Now our app shows "CO2 per paper: 2" instead of "CO2 per paper: 2 kg/kg". (We also plot this information in charts and tables over time).
Could you explain why RubyUnits does this and if this is by design? Would you be open to change this behaviour or make it configurable?
Currently RubyUnits also feels a bit inconsistent regarding this behaviour, since it isn't always applied. For example when I initiate a RubyUnits object and pass "kg/kg" myself, this isn't simplified (Unit.new('2 kg/kg') => 2 kg/kg
). Also if we do a division with different units of the same quantity, then the result could be simplified as well, but this doesn't happen (Unit.new('10 kg') / Unit.new('2 g') => 5 kg/g
instead of 5000
). Following the current behaviour of RubyUnits I would expect these cases to be simplified as well.
Although my suggestion would be to not simplify the unit after a division (or multiplication) at all, but only when explicitly asking for it (e.g. by calling to_base
).
I'm thinking about this.
In the meantime, one clarification... to_base
converts the units to SI and will also simplify the result, it is not the same as just simplifying the units.
@olbrich any update on this?
In the mean time we have applied some hacks to prevent this behaviour (by overriding self.eliminate_terms
with a custom implementation), but it would be nice if we could remove those in the future. Although merging https://github.com/olbrich/ruby-units/pull/241 at least gives us the ability to implement this a bit nicer, once it is released on RubyGems.
I'm thinking about this. In the meantime, one clarification...
to_base
converts the units to SI and will also simplify the result, it is not the same as just simplifying the units.
I understand. We might have two methods: simplify
and to_base
where the latter does both. Or maybe we could have a setting or something like that. At least it would be very helpful for us if it doesn't happen automatically after every calculation (division or multiplication).
No rush or anything, but it would be nice to know what direction you're thinking in.
@kreintjes I'm thinking about using something like #210, where you could define a custom unit that you could define a unit like kg/kg
and then convert to it when needed. I think for that to work you might have to know in advance when you were going to need those units.
An alternative approach if you just want to format the output a particular way....
(Unit.new('10 kg') / Unit.new('5 kg')).to_s('%0.2f kgCO2/kgPaper')
It might also be helpful for you to just define a unit for 'kgCO2' and 'kgPaper' like...
Unit.define('kgCO2') {|unit| unit.definition = Unit.new('1 kg')}
Unit.define('kgPaper') {|unit| unit.definition = Unit.new('1 kg')}
(Unit.new('10 kgCO2') / Unit.new('5 kgPaper')) #=> 2 kgCO2/kgPaper
You are correct that elimination of terms is inconsistent.
Another possible solution would be changing the signature for convert_to
to def convert_to(other, eliminate: true)
, which would allow you to suppress elimination on an individual conversion.
Still thinking about this...
@olbrich thanks for the response. Our issue indeed seems similar to #210 although not exactly. I'm not sure if the proposed solution is workable for us. In our application users can enter custom calculations (which are parsed using the Dentaku gem), so users can perform calculations with all kinds of quantities/units leading to all kinds of results. The kg/kg was just an example, but we could have the same problem with l(iter)/l(iter) and m(eter)/m(eter) to name a few.
We also support lots of different quantities for various reasons: types of fuel, amount of distance with various vehicles but also all kinds of items a company can produce. So for example, they could view a chart of their amount of emitted CO2 per produced kilograms of cement. Or the amount of diesel consumed for transporting liters or kilograms of beer. Although I must say most of our users do the same and for them this issue doesn't even occur. But when they do want something special, we do not (necessarily) know beforehand what (combinations of) units/quantities they use.
For that reason disabling the automatic elimination for calculations with an option/setting would work best for us. Although our current solution with a special Unit class that overrides eliminate_terms seems to work for now :)