{"slug": "qalculate-hacks", "title": "Qalculate Hacks", "summary": "A developer documents advanced hacks for Qalculate, an open-source calculator, including bandwidth estimates, password entropy calculations, and currency conversions. The tool supports command-line and graphical interfaces with features like unit conversions and exchange rate updates.", "body_md": "Qalculate hacks\n\nThis is going to be a controversial statement because some people are absolute nerds about this, but, I need to say it.\n\n[Qalculate](https://qalculate.github.io/) is the best calculator that has ever been made.\n\nI am not going to try to convince you of this, I just wanted to put out my bias out there before writing down those notes. I am a total fan.\n\nThis page will collect my notes of cool hacks I do with\nQalculate. Most examples are copy-pasted from the command-line\ninterface (`qalc(1)`\n\n), but I typically use the graphical interface as\nit's slightly better at displaying complex formulas. Discoverability\nis obviously also better for the cornucopia of features this fantastic\napplication ships.\n\nQalc commandline primer\n\nOn Debian, Qalculate's CLI interface can be installed with:\n\n```\napt install qalc\n```\n\nThen you start it with the `qalc`\n\ncommand, and end up on a prompt:\n\n``` bash\nanarcat@angela:~$ qalc\n>\n```\n\nThen it's a normal calculator:\n\n``` bash\nanarcat@angela:~$ qalc\n> 1+1\n\n  1 + 1 = 2\n\n> 1/7\n\n  1 / 7 ≈ 0.1429\n\n> pi\n\n  pi ≈ 3.142\n\n>\n```\n\nThere's a bunch of variables to control display, approximation, and so on:\n\n```\n> set precision 6\n> 1/7\n\n  1 / 7 ≈ 0.142857\n> set precision 20\n> pi\n\n  pi ≈ 3.1415926535897932385\n```\n\nWhen I need more, I typically browse around the menus. One big issue I\nhave with Qalculate is there are a *lot* of menus and features. I had\nto fiddle quite a bit to figure out that `set precision`\n\ncommand\nabove. I might add more examples here as I find them.\n\nBandwidth estimates\n\nI often use the data units to estimate bandwidths. For example, here's what 1 megabit per second is over a month (\"about 300 GiB\"):\n\n```\n> 1 megabit/s * 30 day to gibibyte \n\n  (1 megabit/second) × (30 days) ≈ 301.7 GiB\n```\n\nOr, \"how long will it take to download X\", in this case, 1GiB over a 100 mbps link:\n\n```\n> 1GiB/(100 megabit/s)\n\n  (1 gibibyte) / (100 megabits/second) ≈ 1 min + 25.90 s\n```\n\nPassword entropy\n\nTo calculate how much entropy (in bits) a given password structure,\nyou count the number of possibilities in each entry (say, `[a-z]`\n\nis\n26 possibilities, \"one word in a 8k dictionary\" is 8000), extract the\nbase-2 logarithm, multiplied by the number of entries.\n\nFor example, an alphabetic 14-character password is:\n\n```\n> log2(26*2)*14\n\n  log₂(26 × 2) × 14 ≈ 79.81\n```\n\n... 80 bits of entropy. To get the equivalent in a [Diceware](https://en.wikipedia.org/wiki/Diceware)\npassword with a 8000 word dictionary, you would need:\n\n```\n> log2(8k)*x = 80\n\n  (log₂(8 × 000) × x) = 80 ≈\n\n  x ≈ 6.170\n```\n\n... about 6 words, which gives you:\n\n```\n> log2(8k)*6\n\n  log₂(8 × 1000) × 6 ≈ 77.79\n```\n\n78 bits of entropy.\n\nExchange rates\n\nYou can convert between currencies!\n\n```\n> 1 EUR to USD\n\n  1 EUR ≈ 1.038 USD\n```\n\nEven fake ones!\n\n```\n> 1 BTC to USD\n\n  1 BTC ≈ 96712 USD\n```\n\nThis relies on a database pulled form the internet (typically the\n[central european bank rates](https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml), see [the source](https://github.com/Qalculate/libqalculate/blob/4acd56ce0c2703af80d6a8857c963d4400f2091f/libqalculate/Calculator-definitions.cc#L3950-L3966)). It will prompt\nyou if it's too old:\n\n```\nIt has been 256 days since the exchange rates last were updated.\nDo you wish to update the exchange rates now? y\n```\n\nAs a [reader pointed out](https://en.osm.town/@mdione/113979012459360601), you can [set the refresh rate for\ncurrencies](https://qalculate.github.io/manual/qalculate-units.html#qalculate-currency), as [some countries](https://en.wikipedia.org/wiki/Economy_of_Argentina) will require way more frequent\nexchange rates.\n\nThe graphical version has a little graphical indicator that, when you mouse over, tells you where the rate comes from.\n\nOther conversions\n\nHere are other neat conversions extracted from my history\n\n```\n> teaspoon to ml\n\n  teaspoon = 5 mL\n\n> tablespoon to ml\n\n  tablespoon = 15 mL\n\n> 1 cup to ml \n\n  1 cup ≈ 236.6 mL\n\n> 6 L/100km to mpg\n\n  (6 liters) / (100 kilometers) ≈ 39.20 mpg\n\n> 100 kph to mph\n\n  100 kph ≈ 62.14 mph\n\n> (108km - 72km) / 110km/h\n\n  ((108 kilometers) − (72 kilometers)) / (110 kilometers/hour) ≈\n  19 min + 38.18 s\n```\n\nCompletion time estimates\n\nThis is a more involved example I often do.\n\nBackground\n\nSay you have started a long running copy job and you don't have the\nluxury of having a pipe you can insert pv(1) into to get a nice\nprogress bar. For example, `rsync`\n\nor `cp -R`\n\ncan have that problem\n(but not `tar`\n\n!).\n\n(Yes, you can use `--info=progress2`\n\nin `rsync`\n\n, but that estimate is\nincremental and therefore inaccurate unless you disable the\nincremental mode with `--no-inc-recursive`\n\n, but then you pay a huge\nup-front wait cost while the entire directory gets crawled.)\n\nExtracting a process start time\n\nFirst step is to gather data. Find the process start time. If you were\nunfortunate enough to forget to run `date --iso-8601=seconds`\n\nbefore\nstarting, you can get a similar timestamp with `stat(1)`\n\non the\nprocess tree in `/proc`\n\nwith:\n\n``` bash\n$ stat /proc/11232\n  File: /proc/11232\n  Size: 0               Blocks: 0          IO Block: 1024   directory\nDevice: 0,21    Inode: 57021       Links: 9\nAccess: (0555/dr-xr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)\nAccess: 2025-02-07 15:50:25.287220819 -0500\nModify: 2025-02-07 15:50:25.287220819 -0500\nChange: 2025-02-07 15:50:25.287220819 -0500\n Birth: -\n```\n\nSo our start time is `2025-02-07 15:50:25`\n\n, we shave off the\nnanoseconds there, they're below our precision noise floor.\n\nIf you're not dealing with an actual UNIX process, you need to figure out a start time: this can be a SQL query, a network request, whatever, exercise for the reader.\n\nSaving a variable\n\nThis is optional, but for the sake of demonstration, let's save this as a variable:\n\n```\n> start=\"2025-02-07 15:50:25\"\n\n  save(\"2025-02-07T15:50:25\"; start; Temporary; ; 1) =\n  \"2025-02-07T15:50:25\"\n```\n\nEstimating data size\n\nNext, estimate your data size. That will vary wildly with the job\nyou're running: this can be anything: number of files, documents being\nprocessed, rows to be destroyed in a database, whatever. In this case,\n`rsync`\n\ntells me how many bytes it has transferred so far:\n\n```\n# rsync -ASHaXx --info=progress2 /srv/ /srv-zfs/\n2.968.252.503.968  94%    7,63MB/s    6:04:58  xfr#464440, ir-chk=1000/982266)\n```\n\nStrip off the weird dots in there, because that will confuse qalculate, which will count this as:\n\n```\n  2.968252503968 bytes ≈ 2.968 B\n```\n\nOr, essentially, three bytes. We actually transferred almost 3TB here:\n\n```\n  2968252503968 bytes ≈ 2.968 TB\n```\n\nSo let's use that. If you had the misfortune of making rsync silent,\nbut were lucky enough to transfer entire partitions, you can use `df`\n\n(without `-h`\n\n! we want to be more precise here), in my case:\n\n```\nFilesystem              1K-blocks       Used  Available Use% Mounted on\n/dev/mapper/vg_hdd-srv 7512681384 7258298036  179205040  98% /srv\ntank/srv               7667173248 2870444032 4796729216  38% /srv-zfs\n```\n\n(Otherwise, of course, you use `du -sh $DIRECTORY`\n\n.)\n\nDigression over bytes\n\nThose are 1 `K`\n\nbytes which is actually (and rather unfortunately)\n`Ki`\n\n, or \"kibibytes\" (1024 bytes), not \"kilobytes\" (1000 bytes). Ugh.\n\n```\n> 2870444032 KiB\n\n  2870444032 kibibytes ≈ 2.939 TB\n> 2870444032 kB\n\n  2870444032 kilobytes ≈ 2.870 TB\n```\n\nAt this scale, those details matter quite a bit, we're talking about a 69GB (64GiB) difference here:\n\n```\n> 2870444032 KiB - 2870444032 kB\n\n  (2870444032 kibibytes) − (2870444032 kilobytes) ≈ 68.89 GB\n```\n\nAnyways. Let's take `2968252503968 bytes`\n\nas our current progress.\n\nOur entire dataset is `7258298064 KiB`\n\n, as seen above.\n\nSolving a cross-multiplication\n\nWe have 3 out of four variables for our equation here, so we can already solve:\n\n```\n> (now-start)/x = (2996538438607 bytes)/(7258298064 KiB) to h\n\n  ((actual − start) / x) = ((2996538438607 bytes) / (7258298064\n  kibibytes))\n\n  x ≈ 59.24 h\n```\n\nThe entire transfer will take about 60 hours to complete! Note that's\nnot the time *left*, that is the *total* time.\n\nTo break this down step by step, we could calculate how long it has taken so far:\n\n```\n> now-start\n\n  now − start ≈ 23 h + 53 min + 6.762 s\n\n> now-start to s\n\n  now − start ≈ 85987 s\n```\n\n... and do the [cross-multiplication](https://en.wikipedia.org/wiki/Cross-multiplication) manually, it's basically:\n\n```\nx/(now-start) = (total/current)\n```\n\nso:\n\n```\nx = (total/current) * (now-start)\n```\n\nor, in Qalc:\n\n```\n> ((7258298064  kibibytes) / ( 2996538438607 bytes) ) *  85987 s\n\n  ((7258298064 kibibytes) / (2996538438607 bytes)) × (85987 secondes) ≈\n  2 d + 11 h + 14 min + 38.81 s\n```\n\nIt's interesting it gives us different units here! Not sure why.\n\nNow and built-in variables\n\nThe `now`\n\nhere is actually a built-in variable:\n\n```\n> now\n\n  now ≈ \"2025-02-08T22:25:25\"\n```\n\nThere is a [bewildering list of such variables](https://qalculate.github.io/manual/qalculate-definitions-variables.html), for example:\n\n```\n> uptime\n\n  uptime = 5 d + 6 h + 34 min + 12.11 s\n\n> golden\n\n  golden ≈ 1.618\n\n> exact\n\n  golden = (√(5) + 1) / 2\n```\n\nComputing dates\n\nIn any case, yay! We know the transfer is going to take roughly 60 hours total, and we've already spent around 24h of that, so, we have 36h left.\n\nBut I did that all in my head, we can ask more of Qalc yet!\n\nLet's make another variable, for that total estimated time:\n\n```\n> total=(now-start)/x = (2996538438607 bytes)/(7258298064 KiB)\n\n  save(((now − start) / x) = ((2996538438607 bytes) / (7258298064\n  kibibytes)); total; Temporary; ; 1) ≈\n  2 d + 11 h + 14 min + 38.22 s\n```\n\nAnd we can plug that into another formula with our start time to figure out when we'll be done!\n\n```\n> start+total\n\n  start + total ≈ \"2025-02-10T03:28:52\"\n\n> start+total-now\n\n  start + total − now ≈ 1 d + 11 h + 34 min + 48.52 s\n\n> start+total-now to h\n\n  start + total − now ≈ 35 h + 34 min + 32.01 s\n```\n\nThat transfer has ~1d left, or 35h24m32s, and should complete around 4 in the morning on February 10th.\n\nBut that's icing on top. I typically only do the cross-multiplication and calculate the remaining time in my head.\n\nI mostly did the last bit to show Qalculate could compute dates and time differences, as long as you use ISO timestamps. Although it can also convert to and from UNIX timestamps, it cannot parse arbitrary date strings (yet?).\n\nOther functionality\n\nQalculate can:\n\n- Plot graphs;\n- Use RPN input;\n- Do all sorts of algebraic, calculus, matrix, statistics, trigonometry functions (and more!);\n- ... and so much more!\n\nI have a hard time finding things it *cannot* do. When I get there, I\ntypically need to resort to programming code in Python, use a\nspreadsheet, and others will turn to more complete engines like\n[Maple](https://en.wikipedia.org/wiki/Maple_(software)), [Mathematica](https://en.wikipedia.org/wiki/Wolfram_Mathematica) or [R](https://en.wikipedia.org/wiki/R_(programming_language)).\n\nBut for daily use, Qalculate is just fantastic.\n\nAnd it's pink! Use it!\n\nGotchas\n\nThere are a couple of things that get me with Qalc, unfortunately.\n\nDecimals precision\n\nI mentioned `set precision`\n\nabove:\n\n```\n> set precision 6\n> 1/7\n\n  1 / 7 ≈ 0.142857\n> set precision 20\n> pi\n\n  pi ≈ 3.1415926535897932385\n```\n\nFractional displays\n\nBut sometimes, I *want* fractional displays (obviously not for π\nbecause it is [irrational](https://en.wikipedia.org/wiki/Irrational_number)). For example, sometimes I work in\ninches, and this would look better as a fraction:\n\n```\n> 8973/12\n\n  8973 / 12 = 747.75\n```\n\nThe trick here is to change the `fraction`\n\nsetting, from the qalc(1) manual:\n\n```\n       fractions, fr (-1* = auto, 0 = off, 1 = exact, 2 = on, 3 = mixed, 4 =\n       long, 5 = dual, 1/n)\n               Determines how rational numbers are displayed (e.g. 5/4 = 1 + 1/4\n               =  1.25).  'long' removes limits on the size of the numerator and\n               denonimator.\n```\n\nNormally, this should be set to `auto`\n\n, so if you've changed it,\nchange it back:\n\n```\nset fractions auto\n```\n\nThen you get the nice mixed output:\n\n```\n> 8973/12\n\n  8973 / 12 = 747 + 3/4 = 747.75\n```\n\nThe `dual`\n\nsetting is also nice:\n\n```\n> set fractions dual\n\n  747.75 = 2991/4 = 747 + 3/4 = 747.75\n```\n\nStrangely, I couldn't figure out how to get the same output in the graphical interface. The closest menu item is Mode > Rational Number Form.\n\nFurther reading and installation\n\nThis is just scratching the surface, the [fine manual](https://qalculate.github.io/manual/) has more\ninformation, including [more examples](https://qalculate.github.io/manual/qalculate-examples.html). There is also of course a\n[qalc(1) manual page](https://manpages.debian.org/bookworm/qalc/qalc.1.en.html) which also ships an [excellent EXAMPLES\nsection](https://manpages.debian.org/bookworm/qalc/qalc.1.en.html#EXAMPLES).\n\nQalculate is packaged for [over 30 Linux distributions](https://repology.org/project/libqalculate/badges), but also\nships packages for Windows and MacOS. There are third-party\nderivatives as well including a [web version](https://qalculator.xyz/) and an [Android\napp](https://f-droid.org/en/packages/com.jherkenhoff.qalculate/).\n\nUpdates\n\nColin Watson liked this blog post and was inspired to [write his own\nhacks](https://www.chiark.greenend.org.uk/~cjwatson/blog/qalculate-time-hacks.html), similar to what's here, but with extras, check it out!\n\nYou can use your Mastodon account to reply to this [post](https://kolektiva.social/@Anarcat/113971985775192655).\n\n[Edited .](https://gitlab.com/anarcat/anarc.at/-/commits/main/blog/2025-02-08-qalculate-hacks.md)", "url": "https://wpnews.pro/news/qalculate-hacks", "canonical_source": "https://anarc.at/blog/2025-02-08-qalculate-hacks/", "published_at": "2026-06-29 21:33:45+00:00", "updated_at": "2026-06-29 21:53:03.704385+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Qalculate", "Debian", "European Central Bank"], "alternates": {"html": "https://wpnews.pro/news/qalculate-hacks", "markdown": "https://wpnews.pro/news/qalculate-hacks.md", "text": "https://wpnews.pro/news/qalculate-hacks.txt", "jsonld": "https://wpnews.pro/news/qalculate-hacks.jsonld"}}