[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

[ANN] Ruby Units

Stefan Lang

8/22/2006 5:23:00 PM

Announcing......

Ruby Units

Version: 0.1.0
Kevin C. Olbrich, Ph.D.
http://www.sc...

Project page: http://rubyforge.org/projects/...

==Introduction
Many technical applications make use of specialized calculations at some
point. Frequently, these calculations require unit conversions to
ensure accurate results. Needless to say, this is a pain to properly
keep track of, and is prone to numerous errors.

==Solution
The 'Ruby units' gem is designed so simplify the handling of units for
scientific calculations. The units of each quantity are specified when
a Unit object is created and the Unit class will handle all subsequent
conversions and manipulations to ensure an accurate result.

==Installation:
This package may be installed using:
gem install ruby-units

==Usage:
unit = Unit.new("1") # constant only
unit = Unit.new("mm") # unit only (defaults to a value of 1)
unit = Unit.new("1 mm") # create a simple unit
unit = Unit.new("1 mm/s") # a compound unit
unit = Unit.new("1 mm s^-1") # in exponent notation
unit = Unit.new("1 kg*m^2/s^2") # complex unit
unit = Unit.new("1 kg m^2 s^-2") # complex unit
unit = Unit("1 mm") # shorthand
unit = "1 mm".to_unit # convert string object
unit = object.to_unit # convert any object using object.to_s

==Rules:
1. only 1 quantity per unit (with 2 exceptions... 6'5" and '8 lbs 8 oz')
2. use SI notation when possible
3. avoid using spaces in unit names

==Unit compatability:
Many methods require that the units of two operands are compatible.
Compatible units are those that can be easily converted into each other,
such as 'meters' and 'feet'.

unit1 =~ unit2 #=> true if units are compatible

==Unit Math:
Unit#+():: Add. only works if units are compatible
Unit#-():: Subtract. only works if units are compatible
Unit#*():: Multiply.
Unit#/():: Divide.
Unit#**():: Exponentiate. Exponent must be an integer, can be
positive, negative, or zero
Unit#inverse:: Returns 1/unit
Unit#abs:: Returns absolute value of the unit quantity. Strips off
the units
Unit#ceil:: rounds quantity to next highest integer
Unit#floor:: rounds quantity down to next lower integer
Unit#round:: rounds quantity to nearest integer
Unit#to_int:: returns the quantity as an integer

Unit will coerce other objects into a Unit if used in a formula. This
means that ..

Unit("1 mm") + "2 mm" == Unit("3 mm")

This will work as expected so long as you start the formula with a Unit
object.

==Conversions & comparisons

Units can be converted to other units in a couple of ways.

unit1 = unit >> "ft" # => convert to 'feet'
unit >>= "ft" # => convert and overwrite original object
unit3 = unit1 + unit2 # => resulting object will have the units of unit1
unit3 = unit1 - unit2 # => resulting object will have the units of unit1

unit1 <=> unit2 # => does comparison on quantities in base
units, throws an exception if not compatible
unit1 === unit2 # => true if units and quantity are the same,
even if 'equivalent' by <=>

==Text Output
Units will display themselves nicely based on the preferred abbreviation
for the units and prefixes.
Since Unit implements a Unit#to_s, all that is needed in most cases is:
"#{Unit.new('1 mm')}" #=> "1 mm"

The to_s also accepts some options.
Unit.new('1.5 mm').to_s("%0.2f") # => "1.50 mm". Enter any valid
format string
Unit.new('1.5 mm').to_s("in") # => converts to inches before printing
Unit.new("2 m").to_s(:ft) #=> returns 6'7"
Unit.new("100 kg").to_s(:lbs) #=> returns 220 lbs, 7 oz

Feedback is welcome, as are feature suggestions.

This release covers most SI, imperial, and customary units.

_Kevin
www.sciwerks.com
--
Posted with http://De.... Sign up and save your mailbox.

19 Answers

Gavin Kistner

8/22/2006 5:35:00 PM

0

Kevin Olbrich wrote:
> Announcing......
>
> Ruby Units

Not to take the wind from your sails (fly, baby, fly!), but:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-...
http://narray.rubyforge.org/quanty/quan...
and my own foray:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-t...

Stefan Lang

8/22/2006 5:51:00 PM

0


On Wednesday, August 23, 2006, at 2:35 AM, Phrogz wrote:
>Kevin Olbrich wrote:
>> Announcing......
>>
>> Ruby Units
>
>Not to take the wind from your sails (fly, baby, fly!), but:
>http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-...
>http://narray.rubyforge.org/quanty/quan...
>and my own foray:
>http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-t...
>
>

The concept isn't new, but I think this approach has the fewest
limitations and is the most general.

Besides, it was a good learning experince.


_Kevin
www.sciwerks.com

--
Posted with http://De.... Sign up and save your mailbox.

Trans

8/23/2006 3:32:00 AM

0


Kevin Olbrich wrote:
> On Wednesday, August 23, 2006, at 2:35 AM, Phrogz wrote:
> >Kevin Olbrich wrote:
> >> Announcing......
> >>
> >> Ruby Units
> >
> >Not to take the wind from your sails (fly, baby, fly!), but:
> >http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-...
> >http://narray.rubyforge.org/quanty/quan...
> >and my own foray:
> >http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-t...
> >
> >
>
> The concept isn't new, but I think this approach has the fewest
> limitations and is the most general.
>
> Besides, it was a good learning experince.

Nice work. Though, you may be interested in Facets' units.rb, written
by Peter Vanbroekhoven. It is about as complete as I can imagine it can
get.

http://facets.rub...

I think the currency conversion functionality is "off line" though. I
need to fix that. It wuld be great if you took a look, maybe you would
like to join the Facets team and work in innovations of your system. I
have for sometime been thinking of releasing parts of Facets in
"bite-sized" portions, staring in fact with units.rb, but I have bigger
plans for distribution, so I've put it off.

T.

Calamitas

8/23/2006 10:51:00 AM

0

On 8/23/06, Trans <transfire@gmail.com> wrote:
> Nice work. Though, you may be interested in Facets' units.rb, written
> by Peter Vanbroekhoven. It is about as complete as I can imagine it can
> get.
>
> http://facets.rub...
>
> I think the currency conversion functionality is "off line" though. I
> need to fix that. It wuld be great if you took a look, maybe you would
> like to join the Facets team and work in innovations of your system. I
> have for sometime been thinking of releasing parts of Facets in
> "bite-sized" portions, staring in fact with units.rb, but I have bigger
> plans for distribution, so I've put it off.

If someone plans to work on units.rb, it might be interesting to know
I have a newer version lying around, but I haven't gotten around to
completing it or thoroughly testing it. Trans, I'll send it to you,
and you can arrange its further completion at your leisure.

Stefan Lang

8/23/2006 12:56:00 PM

0


On Wednesday, August 23, 2006, at 12:35 PM, Trans wrote:
>
>Kevin Olbrich wrote:
>> On Wednesday, August 23, 2006, at 2:35 AM, Phrogz wrote:
>> >Kevin Olbrich wrote:
>> >> Announcing......
>> >>
>> >> Ruby Units
>> >
>> >Not to take the wind from your sails (fly, baby, fly!), but:
>> >http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-...
>> >http://narray.rubyforge.org/quanty/quan...
>> >and my own foray:
>> >http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-t...
>> >
>> >
>>
>> The concept isn't new, but I think this approach has the fewest
>> limitations and is the most general.
>>
>> Besides, it was a good learning experince.
>
>Nice work. Though, you may be interested in Facets' units.rb, written
>by Peter Vanbroekhoven. It is about as complete as I can imagine it can
>get.
>
> http://facets.rub...
>
>I think the currency conversion functionality is "off line" though. I
>need to fix that. It wuld be great if you took a look, maybe you would
>like to join the Facets team and work in innovations of your system. I
>have for sometime been thinking of releasing parts of Facets in
>"bite-sized" portions, staring in fact with units.rb, but I have bigger
>plans for distribution, so I've put it off.
>
>T.
>
>

Hey, amazing all the interesting stuff that pops up when you know where
to look for it.

After a 15 minute look, I can see some issues with the current version
of Units in facets.

1. It doesn't implement Comparable.
1.cm < 2.m #=> throws an exception in Facets
"1 cm".unit < "2 m".unit #=> returns true in ruby-units

2. The binary prefixes are incorrect (at least in the RDoc). They
should be like 'kibi = 2**10' and 'mebi = 2**20'.

3. Facet Units doesn't seem to do temperature conversions. Maybe it
does, but I can't find any documentation on it.

4. I haven't found a simple way to convert a string into a Unit using
Facets. One reason that ruby-units does this is because I wanted to
make it easy for users to provide units as input and then parse them.
The facets Units seem to work fine if you know which units you want to
use when you write your program.

5. ruby-units is much more flexible in terms of what units it recognizes
with the default configuration.
1.attoparsec/microfortnight.to(inch/s) # => fails in Facets
"1 attoparsec/microfortnight".unit("in/s") #=> "1.0043269330917 in/s"
in ruby-units

6. Facets seems to get in trouble when the name of a unit collides with
a ruby keyword
1.m.to(in) #=> causes a parse error in Facets
This isn't an issue in ruby-units since all the units are specified as
strings.

7. ruby-units does not do dynamic currency conversions right now.

8. Facet Units does not seem to implement may Numeric methods like (abs,
ceil, floor, to_i, round, etc..). This works as you would expect with
ruby-units.

9. Facet Units seems to be unable to simplify units in some cases..
(1.m * 1.m) / (1.cm * 1.cm) #=> 1 m**2/cm**2
I can't figure out how to convert this result to a float.

In ruby-units, the equivalent would be.
("1 m".unit * "1 m".unit / ("1 cm".unit * "1 cm".unit)).to_base.to_f
#=> 10000.0

Disclaimer: Some of these observations may be erroneous due to my
unfamiliarity with this package. Feel free to correct them.

I'd be happy to work with Facets to improve it's handling of units.

_Kevin
www.sciwerks.com

--
Posted with http://De.... Sign up and save your mailbox.

Calamitas

8/23/2006 3:05:00 PM

0

On 8/23/06, Kevin Olbrich <devlists-ruby-talk@devlists.com> wrote:
> Hey, amazing all the interesting stuff that pops up when you know where
> to look for it.
>
> After a 15 minute look, I can see some issues with the current version
> of Units in facets.
>
> 1. It doesn't implement Comparable.
> 1.cm < 2.m #=> throws an exception in Facets
> "1 cm".unit < "2 m".unit #=> returns true in ruby-units
>
> 2. The binary prefixes are incorrect (at least in the RDoc). They
> should be like 'kibi = 2**10' and 'mebi = 2**20'.

I have no problem adding these. However, personally, I don't like
kibibyte and prefer kilobyte, and I expect I'm not alone. Facets'
units.rb is flexible enough to allow kibi = 2**10 and kilo = 10**3
(following the IEC convention,
http://en.wikipedia.org/wiki/Bin...) next to kilo = 2**10. The
only issue is which to make the default.

> 3. Facet Units doesn't seem to do temperature conversions. Maybe it
> does, but I can't find any documentation on it.

It doesn't as temperature conversions are ill-defined. As you know,
both absolute temperatures and temperature differences have the same
unit. Any operation on two temperatures expressed in different units
cannot be correct for absolute temperatures and temperature
differences. This is an inherent problem, so we had three choices: do
no conversions, use the conversion for absolute temperatures, or use
the conversion for temperature differences. We chose the first of
these three. We're open to additional ideas on this.

> 4. I haven't found a simple way to convert a string into a Unit using
> Facets. One reason that ruby-units does this is because I wanted to
> make it easy for users to provide units as input and then parse them.
> The facets Units seem to work fine if you know which units you want to
> use when you write your program.

I remember implementing this, so it should be present in the version I
sent Trans.

> 5. ruby-units is much more flexible in terms of what units it recognizes
> with the default configuration.
> 1.attoparsec/microfortnight.to(inch/s) # => fails in Facets
> "1 attoparsec/microfortnight".unit("in/s") #=> "1.0043269330917 in/s"
> in ruby-units
>
> 6. Facets seems to get in trouble when the name of a unit collides with
> a ruby keyword
> 1.m.to(in) #=> causes a parse error in Facets
> This isn't an issue in ruby-units since all the units are specified as
> strings.

This is indeed a bit of a problem. Again, if I remember correctly, the
new version should handle strings as well, though maybe/probably not
for every operation.

> 7. ruby-units does not do dynamic currency conversions right now.
>
> 8. Facet Units does not seem to implement may Numeric methods like (abs,
> ceil, floor, to_i, round, etc..). This works as you would expect with
> ruby-units.
>
> 9. Facet Units seems to be unable to simplify units in some cases..
> (1.m * 1.m) / (1.cm * 1.cm) #=> 1 m**2/cm**2
> I can't figure out how to convert this result to a float.
>
> In ruby-units, the equivalent would be.
> ("1 m".unit * "1 m".unit / ("1 cm".unit * "1 cm".unit)).to_base.to_f
> #=> 10000.0

I remember that this is by design, although I don't remember the
actual reason behind this design decision. I think it was because this
automatic conversion may be unwanted because the conversion introduces
rounding errors in some cases, and it is better to postpone the
conversion until the programmer explicitly requests this. This is done
using #to, but that doesn't work for unitless quantities as in your
example above (unless you do .to(m/m) or so), so we need a to_f method
indeed.

> Disclaimer: Some of these observations may be erroneous due to my
> unfamiliarity with this package. Feel free to correct them.

I have a disclaimer of my own: it is not a finished library, and all
of the issues above that I haven't addressed were planned to be added
at some point. I have been focussing my attention on getting the base
functionality right. Your observations above shouldn't be hard to add.

> I'd be happy to work with Facets to improve it's handling of units.

I'll work on addressing your observations above this evening, and I'll
send the new code to Trans and you. Thanks for your interest, and your
help.

Peter

Ara.T.Howard

8/23/2006 3:16:00 PM

0

Paul Lutus

8/23/2006 4:12:00 PM

0

Peter Vanbroekhoven wrote:

/ ...

>> 3. Facet Units doesn't seem to do temperature conversions. Maybe it
>> does, but I can't find any documentation on it.
>
> It doesn't as temperature conversions are ill-defined.

No, actually, temperature conversions are perfectly well-defined.
Unfortunately, absolute temperature conversions require two mathematical
operations instead of one (a multiplier and an offset), which sets them
apart from nearly all other conversions. It even sets them apart from
temperature differential conversions.

> As you know,
> both absolute temperatures and temperature differences have the same
> unit. Any operation on two temperatures expressed in different units
> cannot be correct for absolute temperatures and temperature
> differences.

That is because converting a temperature differential is not the same as
converting a temperature. But each of the operations is clearly defined.

> This is an inherent problem, so we had three choices: do
> no conversions, use the conversion for absolute temperatures, or use
> the conversion for temperature differences.

There is a third choice -- convert temperatures and temperature
differentials separately. Name one absolute temperatures, and the other
delta-t or something similar.

It is basically a Calculus issue. You may know that taking a differential
(or a derivative) involves the loss of information, and when the converse
operation (integration, a term only loosely applicable here) is performed,
a constant (usually unknown) is included to remind the practitioner about
the lost information. In the same way, moving from a temperature to a
differential of temperature loses information, so the reciprocal operation
(difference to absolute) must be carefully handled (when it can be
performed at all).

Someone versed in Calculus wouldn't think of mixing functions and their
derivatives without being vigilant that they represent different things.
The temperature conversion problem should be looked on in the same way.

> We chose the first of
> these three. We're open to additional ideas on this.

Well, this is just something to think about. I've written a lot of unit
conversion routines over the years and I haven't considered handling
temperatures and temperature differentials separately, but it's an obvious
solution.

I just noticed something. The Linux utility "units" handles both temperature
and temperature differences, and they are distinguished by syntax:

$ units "tempC(0)" tempF # absolute temperature
32

$ units "32 degF" degC # temperature difference
* 17.777778
/ 0.05625

So it seems it has been done.

--
Paul Lutus
http://www.ara...

Stefan Lang

8/23/2006 4:15:00 PM

0


On Thursday, August 24, 2006, at 12:04 AM, Peter Vanbroekhoven wrote:
>On 8/23/06, Kevin Olbrich <devlists-ruby-talk@devlists.com> wrote:
>> Hey, amazing all the interesting stuff that pops up when you know where
>> to look for it.
>>
>> After a 15 minute look, I can see some issues with the current version
>> of Units in facets.
>>
>> 1. It doesn't implement Comparable.
>> 1.cm < 2.m #=> throws an exception in Facets
>> "1 cm".unit < "2 m".unit #=> returns true in ruby-units
>>
>> 2. The binary prefixes are incorrect (at least in the RDoc). They
>> should be like 'kibi = 2**10' and 'mebi = 2**20'.
>
>I have no problem adding these. However, personally, I don't like
>kibibyte and prefer kilobyte, and I expect I'm not alone. Facets'
>units.rb is flexible enough to allow kibi = 2**10 and kilo = 10**3
>(following the IEC convention,
>http://en.wikipedia.org/wiki/Bin...) next to kilo = 2**10. The
>only issue is which to make the default.

My only suggestion is to name the binary prefixes correctly, and allow
people to use the SI ones as well. I've tried to follow the standards
when possible, even if I don't like Mebibits.

>
>> 3. Facet Units doesn't seem to do temperature conversions. Maybe it
>> does, but I can't find any documentation on it.
>
>It doesn't as temperature conversions are ill-defined. As you know,
>both absolute temperatures and temperature differences have the same
>unit. Any operation on two temperatures expressed in different units
>cannot be correct for absolute temperatures and temperature
>differences. This is an inherent problem, so we had three choices: do
>no conversions, use the conversion for absolute temperatures, or use
>the conversion for temperature differences. We chose the first of
>these three. We're open to additional ideas on this.

My solution to this was to scale the temperature units by size (as a
differential) except in the case where the conversion was from one
temperature unit to another. In that case, it does the correct conversion.

When temperatures are used in compound units, they never represent an
absolute temperature value. If you do the absolute conversion when they
are the only units there, then you can do proper temperature math.

Although it appears that my solution has it's own problems. You can add/
subtract temperatures and the get the new absolute value, but you may
want the differential value instead. I'll have to think about that one
a bit more.


_Kevin
www.sciwerks.com

--
Posted with http://De.... Sign up and save your mailbox.

Stefan Lang

8/23/2006 4:39:00 PM

0


On Thursday, August 24, 2006, at 1:15 AM, Paul Lutus wrote:
>Peter Vanbroekhoven wrote:
>
>/ ...
>
>>> 3. Facet Units doesn't seem to do temperature conversions. Maybe it
>>> does, but I can't find any documentation on it.
>>
>> It doesn't as temperature conversions are ill-defined.
>
>No, actually, temperature conversions are perfectly well-defined.
>Unfortunately, absolute temperature conversions require two mathematical
>operations instead of one (a multiplier and an offset), which sets them
>apart from nearly all other conversions. It even sets them apart from
>temperature differential conversions.
>
>> As you know,
>> both absolute temperatures and temperature differences have the same
>> unit. Any operation on two temperatures expressed in different units
>> cannot be correct for absolute temperatures and temperature
>> differences.
>
>That is because converting a temperature differential is not the same as
>converting a temperature. But each of the operations is clearly defined.
>
>> This is an inherent problem, so we had three choices: do
>> no conversions, use the conversion for absolute temperatures, or use
>> the conversion for temperature differences.
>
>There is a third choice -- convert temperatures and temperature
>differentials separately. Name one absolute temperatures, and the other
>delta-t or something similar.
>
>It is basically a Calculus issue. You may know that taking a differential
>(or a derivative) involves the loss of information, and when the converse
>operation (integration, a term only loosely applicable here) is performed,
>a constant (usually unknown) is included to remind the practitioner about
>the lost information. In the same way, moving from a temperature to a
>differential of temperature loses information, so the reciprocal operation
>(difference to absolute) must be carefully handled (when it can be
>performed at all).
>
>Someone versed in Calculus wouldn't think of mixing functions and their
>derivatives without being vigilant that they represent different things.
>The temperature conversion problem should be looked on in the same way.
>
>> We chose the first of
>> these three. We're open to additional ideas on this.
>
>Well, this is just something to think about. I've written a lot of unit
>conversion routines over the years and I haven't considered handling
>temperatures and temperature differentials separately, but it's an obvious
>solution.
>
>I just noticed something. The Linux utility "units" handles both
>temperature
>and temperature differences, and they are distinguished by syntax:
>
>$ units "tempC(0)" tempF # absolute temperature
> 32
>
>$ units "32 degF" degC # temperature difference
> * 17.777778
> / 0.05625
>
>So it seems it has been done.
>
>--
>Paul Lutus
>http://www.ara...
>

Yeah, I'm considering a variation on this approach. It's a little
tricky, but not insurmountable.

_Kevin
www.sciwerks.com

--
Posted with http://De.... Sign up and save your mailbox.