top | item 25657311

GNU Units

421 points| tosh | 5 years ago |gnu.org | reply

203 comments

order
[+] typhonius|5 years ago|reply
My first exposure to GNU Units was when I read the story about emails failing if they were to be sent more than 500 miles.

I’m sure it’s popped up here before but here’s a link for those who haven’t come across it: https://www.ibiblio.org/harris/500milemail.html

[+] lozf|5 years ago|reply
Same here back in the early aughts, but it took me a while to really dig in and discover that units also handles times too.

e.g. units "sec $(echo $SECONDS)" "day;hr;min;sec"

[+] dheera|5 years ago|reply
First time user. Failed on me.

    You have: 25 C
    You want: K
    conformability error
        25 A s
        1 K

    You have: 1 cup flour
    Unknown unit 'flour'
I think I'll stick with Google.
[+] generalizations|5 years ago|reply
Last time this showed up on here, a poster claimed to be the consultant who did the upgrade and caused the problem.
[+] cgranier|5 years ago|reply
Same here... And I think it was quoted here a week or so ago again. Great story.
[+] blauditore|5 years ago|reply
Fun story, but the numbers don't add up for me:

Wouldn't the signal have to do a full round trip within the timeout of 3 ms, meaning it could not go beyond 580 / 2 = 290 miles?

Additionally, the connection from A to B is usually not a straight line, and at that time fiber lines were much less widespread. All these factors combines make it unlikely that even 200 miles could be reached...

[+] Faaak|5 years ago|reply
A simple example I used recently in order to guesstimate how much energy is needed to heat 300liters of water by 5K:

  You have: 5K * 300kg * water_specificheat
  You want: kWh
  * 1.7433333
really easy to use.

How much power could you obtain with a small water turbine if you had 10m of head and 1l/s ? Easy !

  You have: 10m * 1kg/s * gravity
  You want: W
  * 98.0665
[+] derefr|5 years ago|reply
I’ve always wondered why units(1) isn’t a library. I’d love to have access to abstract “united quantities” and “united measurements” in my HLL of choice, rather than needing to switch to a special-purpose tool (units, Frink) or a statistical-analysis language like R just to get them.

Sometimes I need to bust out stoichiometry-like unit-balancing in the middle of my code, and I want type enforcement that I’m getting the right units in the output! Sometimes I want to do a series of floating-point calculations, and I need to put error-bars on the result, and it’d be great if those were tracked for me in the form of a measurement ADT that tracked sig-figs. Etc.

My only guess for why there’s no libunits, is that it’d be a obtrusive black-box of operational non-guarantees if it was implemented in C, given that what Units does — if naively implemented — would be heavy on arbitrary memory allocations, and basically necessitate garbage collection.

It’d make much more sense for a libunits to exist as a C++-ish “template library” that takes an allocator as an argument; but that doesn’t really help anyone who wants to use any language other than C++ (as the template parameters can’t be exposed in the C wrapper code that other languages FFI to.)

(Before someone asks, you could get a limited kind of united-quantities — ones that can only represent “realistic” units — with a static per-qty bitfield representing the compiled-in units. But this wouldn’t really let you represent arbitrary unexpected “unit polynomial” qtys, e.g. m^5s^-3. This might seem fine, but sometimes intermediate quantities in formulae look like that, even though they work out to something sensible when everything is multiplied out.)

Even if there couldn’t be a single units library implementation, it’d at least make sense for there to be 1. a canonical libunits-data release (sort of like tzdata), that individual library impls could pull in; and 2. a high-level API spec or reference-impl of what a libunits library for a given language-runtime would look like (sort of like how every HLL has copied JodaTime’s datetime design.)

[+] SoSoRoCoCo|5 years ago|reply
The source isn't that big, I just downloaded 2.21 source and it is one directory with about ~45 files, and the majority of bytes are for /doc/dvi binaries, only 5 c files and a post Yacc'd tab file for parsing the units definitions file. Surprisingly simple now that I look at it.

Heck... I was going ask you to write it, but now I'm thinking this could be a fun weekend project.

I can see one function in that library:

    bool convert(const char *from, const char *to, double input, double *output);
No need to make it more complex for starters. If you want to make an .hxx Boost-like class around it, that's outta my league!

EDIT: markdown help

EDIT: added a status return instead of val return to check for conversion correctness (bool is newer C)

[+] dktoao|5 years ago|reply
There are heaps of libraries for all languages because it is a fairly fun and straight forward project. I personally created this one because I was frustrated with how slow and clunky the existing javascript libraries were:

https://github.com/GhostWrench/pqm

Also, I open sourced just the unit database (in JSON format) for anyone interested in making their own version:

https://github.com/GhostWrench/unitdb

[+] mhh__|5 years ago|reply
Keeping track of units was one of the first ever uses of C++ templates (one of the Bjarne books IIRC mentions it existing prior to the STL), but was apparently reinvented multiple times later.
[+] kumarsw|5 years ago|reply
Looks cool. If the poster is affiliated with the project, some suggestions:

1. I don't know what I am looking at with the examples. I think that this is an interactive session with the program, but this is not clear. 2. It is also unclear how to start the program as the executable name is not specified. This and the former point could be addressed by including one of those gifs of an interactive session that are popular in GitHub readmes these days. Sure, they are a bit gimmicky, but still useful. 3. It is not clearly stated if this is an executable program or a library. I believe it is the former, but this is nowhere in the introduction. 4. Probably this is included with a number of package managers. If that is the case, instructions for installing via a package manager would be helpful, especially since the name is not particularly unique.

[+] Enginerrrd|5 years ago|reply
No please don't use a gif. That's a terrible way to present information and leads to accessibility issues in documentation where it has no business. Instead, just show a shell prompt and the command needed to launch the program.
[+] laumars|5 years ago|reply
This is a GNU implementation of an old UNIX tool. It’s older than Linux, let alone package managers. There’s also BSD and other implementations available (the BSD version comes pre-installed on macOS).

This isn’t some new tool that is uncommon in UNIX systems, it’s something that a lot of OSs ship with their base install and have done for several decades.

The reason why that matters is because documentation was very different back then. People relied on ‘man’ pages and physical binders with printed instructions. READMEs did exist but they were plain text (not even markdown) and that was generally just there to explain how to compile the source (the compilation would create man pages)

[+] wyldfire|5 years ago|reply
Maybe a shell script showing the inputs more explicitly would help?

    echo -e '500 miles\nkm' | gnu-units-executable-name
But I'm pretty sure from reading the post that units prompts you first for 'you have' (units and/or measurement to convert) and then prompts you for 'you want' (units to convert to).
[+] adrianmonk|5 years ago|reply
I recommend the "-1" (also called "--one-line") flag for bc.

It takes away the extra (to me) reciprocal conversion factors. (Note: it's the number one, not a lowercase "L".)

Without:

    $ units 
    Currency exchange rates from FloatRates (USD base) on 2019-05-31 
    3460 units, 109 prefixes, 109 nonlinear units
    
    You have: inch
    You want: cm
     * 2.54
     / 0.39370079
    You have: 
With:

    $ units -1
    Currency exchange rates from FloatRates (USD base) on 2019-05-31 
    3460 units, 109 prefixes, 109 nonlinear units
    
    You have: inch
    You want: cm
     * 2.54
    You have: 
To me the reciprocals are just clutter. If I want a reciprocal, I will just type the two parts of my query in the opposite order. I'd even say they're confusing because you have to look at them understand why there are two numbers.

(Also on the subject of flags, I'd like one that suppresses the first two lines of output but not the prompts like "You have:".)

[+] scaladev|5 years ago|reply
Did you paste that printout from a recent run of units? If so, the currency rates are pretty useless. You can configure the system to update them daily (or however you like) with something like this:

  $ cat /etc/systemd/system/units-currency-update.service
  [Unit]
  Description=Update units(1) currency rates
  
  [Service]
  Type=oneshot
  Nice=19
  
  ExecStart=/usr/bin/units_cur
  
  
  
  $ cat /etc/systemd/system/units-currency-update.timer
  [Unit]
  Description=Update units(1) currency rates
  
  [Timer]
  OnCalendar=daily
  AccuracySec=3h
  RandomizedDelaySec=3h
  Persistent=true
  
  [Install]
  WantedBy=timers.target
  
  
  # systemctl daemon-reload
  # systemctl enable units-currency-update.timer
[+] adrianmonk|5 years ago|reply
Corrections (b/c too late to edit):

(1) The flag isn't for bc, of course; it's for units. I'm always running the wrong one, so no surprise I mixed them up again.

(2) Should read "look at them to understand" near the end.

[+] Symbiote|5 years ago|reply
I started using this tool some years ago after I found out the CO₂ cost of a Google search. I don't need a web query when I search "40000lb in tonnes" when reading an American news article, for example.

  units 40000lb tonnes
   * 18.143695
It even includes currencies. "sudo units_cur" will update the exchange rate data file, if you need that.

  units 50GBP USD
   * 68.143948
[+] hprotagonist|5 years ago|reply
> Like many similar programs, it can handle multiplicative scale changes. It can also handle nonlinear conversions such as Fahrenheit to Celsius

how is

  C = (5/9)(F-32)
not linear?
[+] bjeds|5 years ago|reply
How does GNU Units compare to Frink ( https://frinklang.org/ )?
[+] maxerickson|5 years ago|reply
Units is older, frink is a lot bigger, it's a whole programming environment.

Frink started from and extended the units defined by Units, I don't know if anything has gone in the other direction.

Later: for simpler calculations an interesting feature frink adds is the ability to do interval arithmetic. Terms can be specified as ranges that are then carried through the calculations to the result.

[+] samatman|5 years ago|reply
The author of Frink takes particular pride in doing unit maths correctly.

For example, if the conversion between two units is defined by statute to be some weird ratio, Frink will use that, and not merely the best f64 approximation of that ratio.

As indicated by a sibling comment, Frink also handles interval maths, and in general it just has a remarkable amount of features, being a fully-fledged programming language.

It's a pity it isn't open-source, the author says he doesn't want the aggravation of having to deal with pull requests and so on, and just wants to work on his software project on his own. Which, ok, that's fair: but at least Lua and SQLite don't accept contributions from outside the team, so there's a model for releasing open-source software without having to collaborate with the general public.

No question that it would increase the size of his inbox though, so I get it.

[+] jillesvangurp|5 years ago|reply
Looks like it is comparable to javax.measure (https://jcp.org/en/jsr/detail?id=363). I used an implementation of that a few years ago: https://github.com/unitsofmeasurement/uom-se

It's a complex domain, especially if you get down to having more complex units composed of other units and want to do conversions between metric and imperial. In our case we were dealing with material properties (chemical, physical, magnetic, etc.) and different countries and companies using different ways to record characteristics for materials.

[+] johnisgood|5 years ago|reply
GNU Units is a beautiful piece of software. I keep using it for everything. You can convert between currencies, too.

If GNU Units cannot do something, I resort to using Maxima[1].

[1] https://maxima.sourceforge.io

[+] ISL|5 years ago|reply
If Units can convert between currencies, how does it source the exchange rates? They change on sub-second time scales and bid/ask spreads make the notion of a rate somewhat uncertain.

Edit: answering my own question. There are multiple providers, some requiring API-key signup, but the answer is far from definitive: https://www.gnu.org/software/units/manual/html_node/Currency...

[+] Ajedi32|5 years ago|reply
I've been using WolframAlpha for this sort of thing. The idea of using something fully local and open-source does have some appeal, but it's hard to compete with the convenience of Ctrl+T "wo" <Tab> <Query> <Enter>.
[+] sequoia|5 years ago|reply
I must be dense but what do the star and the slash mean? It looks like "multiply by" and "divide by" but it appears to have results of the conversion next to the star... Do the docs explain this and I missed it?

    You have: 1 lbs
    You want: kg
     * 0.45359237
     / 2.2046226
    You have: 2 lbs
    You want: kg
     * 0.90718474
     / 1.1023113
    You have: 2.4 lbs
    You want: kg
     * 1.0886217
     / 0.91859276
[+] djur|5 years ago|reply
It's just showing the inverse. It makes more sense if you don't enter a number for the first unit:

   You have: kg/day
   You want: lb/hr
 * 0.091859276
 / 10.886217
[+] jxy|5 years ago|reply
It's not about GNU.

V6 Unix (circa 1975) had it: http://man.cat-v.org/unix-6th/6/units

Your macOS have the BSD version:

    % units -v
    
      units version 1.0  Copyright (c) 1993 by Adrian Mariano
                        This program may be freely distributed
    usage: units [-f unitsfile] [-q] [-v] [from-unit to-unit]
[+] boomboomsubban|5 years ago|reply
I'm not sure of the total history, but "by Adrian Mariano" means macOS uses GNU units. Wiki says they forked a copy before the license change.
[+] boogies|5 years ago|reply
It’s about Unix, and GNU’s Not happens to be the best implementation of it. Which is why macOS copies pieces of it, despite needing to use obsolete versions in order to comply with Apple’s hatred for end-user freedom.
[+] BenjiWiebe|5 years ago|reply
I love being able to convert from millilightseconds to miles, and vice versa. You can figure minimum latency for a given distance or maximum distance for a given latency.
[+] danaliv|5 years ago|reply
Oh thank goodness, I can stop using Google for this. (Aside: Is anyone else annoyed that Google doesn't understand what a hectopascal is? It interprets hPa as Pa, which is obnoxious. Every time I convert to or from hPa I have to do it twice: once in hPa and then again in millibars.)
[+] LeonM|5 years ago|reply
The documentation seems a bit incomplete, not what I'm used to with GNU. There seems to be no list of all units supported.

I tried converting torque "100 ft lbf" to standard ISO notation (Nm). Let's see:

  units "100 ft lbs" "Nm"
  > Unknown unit 'Nm'

  units "100 ft lbs" "nm"
  > conformability error

  units "100 ft lbs" "newton meter"
  > * 135.58
How am I supposed to know that 'newton' must be written in full (though 'ft' and 'lbs' can be abbreviated)? Searching for 'newton' in the manpage yields 0 results.
[+] tsujp|5 years ago|reply
I keep using different tools to do conversions so now I can unify that all into Units and get my speed in furlongs per fortnight as the ancient prophecies foretold.

Rejoice!

(but for real this is top I’m replacing multiple other tools with Units)

[+] enriquto|5 years ago|reply
I love it, everything is there!

    You have: kilometers per hour
    You want: attoparsecs per microfortnight
            * 10.889018
[+] visviva|5 years ago|reply
I absolutely adore this program. It works exactly like I expect, every time. Sometimes I'll just think about what a nice tool it is, even when I'm not using it.
[+] dredmorbius|5 years ago|reply
A favourite tool, which I also found via Trey Harris's speed-of-light email post.

I've written a few quick guides and examples using GNU units:

GNU 'units' utility and energy / resource calculations

https://old.reddit.com/r/dredmorbius/comments/1x9u0f/gnu_uni...

How many Hiroshima bombs in a Ferrari, with mass-energy conversion (or how I learned to extend GNU units)

https://old.reddit.com/r/dredmorbius/comments/1yvxde/how_man...

And for assessing specifc alternative energy claims:

Boeing's Biofuel "Breakthrough" -- Less than overwhelming

https://old.reddit.com/r/dredmorbius/comments/1wo2hl/boeings...

[+] benibela|5 years ago|reply
I have been using qalc for that

How does it compare?

  $ qalc

  > furlongs per fortnight

   furlong / fortnight = 1 fur / fortnight

 > to m/s

   1 fur / fortnight = approx. 0,0001663095238 m / s

 > 17 yards + 2 feet + 5 inches

   (17 * yard) + (2 * foot) + (5 * inch) = 17 yd + 2 ft + 5 in

 > to meter

   17 yd + 2 ft + 5 in = 16,2814 m

 >
[+] JNRowe|5 years ago|reply
For use cases like that it is incredibly similar if you give the --verbose flag:

    $ units --verbose
    [header]
    You have: furlongs per fortnight
    You want: m/s
            furlongs per fortnight = 0.00016630952 m/s
            furlongs per fortnight = (1 / 6012.8848) m/s
    You have: 17 yards + 2 feet + 5 inches
    You want: meter
            17 yards + 2 feet + 5 inches = 16.2814 meter
            17 yards + 2 feet + 5 inches = (1 / 0.06141978) meter
Personally, I find qalc via qalculate-gtk more useful for exploratory sessions but I still use units an awful lot.