I need to design a function to perform the basic arithmetic operations that are addition (+)
, subtraction (-)
, multiplication (x)
, and division (/)
between 2 numbers.
That function takes 3 arguments:
–number1
: composed of a value
and a unit
.
–number2
: compoased of a value
and a unit
.
–operation_type
: one of the 4 aforementioned operations.
and should return:
–number3
: composed of a value
and a unit
.
Returning number3
‘s value
is easy as all I need to do is use conditional statements to perform the corresponding operation (e.g. if (operation_type == 'addition') { number3.value = number1.value + number2.value; }
).
However I’m having difficulties figuring out how I should represent and deal with the unit
(for multiplication
and subtraction
operations, as for addition
and subtraction
it remains the same) in a way that I can chain up multiple operations and properly update the resulting unit
every time. Here is an example:
operations type: multiplications
number1.unit: Kw
number2.unit: h / user / year
number3.unit: Kwh / user / year _
|
number1.unit: Kwh / user / year <-
number2.unit: user
number3.unit: Kwh / year _
|
number1.unit: Kwh / year <-
number2.unit: year
number3.unit: Kwh
...
My only constraint is that the unit
must initially be represented as a string
because it is stored in the database, then we can parse parse it into an object/array
as needed.
Some of the problems I’m facing:
Q1: how to ensure consistent order in the resulting unit (e.g. h x Kw
and Kw x h
should both give Kwh
)?
Q2: how to deal with complex units (e.g. foo / Kw x h / bar
)?
And because hope dies last:
Q3: Are there any known algorithms / design patterns for dealing with this?
If you just need to deal with physical quantities, then you can choose an n-dimensional system of physical units (length, mass, time, charge, etc.) that fits your domain. Any physical unit is a product of powers of the fundamental units (positive and negative): e.g. force = mass * length * time^-2. When you multiply physical quantities, you can just add the powers of the fundamental units. If you need to handle fractional powers, I would represent them as ratios (1/3), not floating point (0.33333333)
Ordering for human display is largely a matter of custom. Typically the order is positive powers of mass, length, time in the numerator and denominator, e.g. km-m^2/sec^2. But there are many exceptions. For example, Hubble’s constant has dimension time^-1, but it is typically expressed as velocity / distance, e.g. km/sec / megaparsec.
As far as I know, C++ is the only popular language with a type system powerful enough to conveniently verify physical unit balance at compile time. There are several C++ libraries available, including one in Boost. If you are not using C++, you may want to look at one of them for inspiration.
2
I would just create a lookup table.
It’s the fastest way to guarantee that when you get kW
and h
, regardless of order, that you’ll come back with kW*h
.
The only downside is if you have a very large number of combinations then it can be a pain to put the table together.