Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Kalk, A calculator with math syntax, complex numbers (strct.net)
239 points by paddim8 7 months ago | hide | past | favorite | 84 comments

I immediately found a few Unicode features I hoped were supported but aren’t.

Superscripts: firstly numerals, like 3² = 9, but ideally then letters as well, e.g. 3ⁱ = 3^i. Might be suitable to support superscripts to define nth roots, too, e.g. ⁵√. tan¯¹ can be a thing too.

Subscripts: same deal; log₂ 31 = log(31, 2).

Proper arithmetic operators: times (×), minus (−), division (÷). Also fraction slash (⁄), which can be preceded and succeeded either by normal numerals (e.g. 12⁄34) or by superscripts and subscripts (e.g. ⁵⁶⁄₇₈). (Full font support for fraction slash is weak, but generally tolerable even if imperfect.) Also the prebaked fractions like ½ and ⅜.

Also mixed fractions: I reckon 1 2/3 should be parsed as 1+2/3, not 12/3. Them Unicode fractions can join in here too, with 1⅔ (using a prebaked fraction) being 1+2/3, or 1²³⁄₄₅ (using superscript, fraction slash, subscript) being 1+23/45.

Cubic and quartic roots: ∛ and ∜.

At this point it’s worth just looking through the whole Symbol, Math Unicode category and implementing everything applicable. Hmm, set operations, lots of fun symbols there.

Lots of fun spaces too, e.g. where I wrote log₂ 31 earlier I wanted to use NARROW NO-BREAK SPACE after the ₂, but alas, HN normalises it to a plain old space. That space gets used as a number grouping separator especially, avoiding the whole ,/. localisation problem without being too wide.

Oh yes! I have thought about the subscript/superscript thing, but didn't think of these other things. That would actually be great.

kalk is a calculator that has syntax highlighting, automatically turns names into symbols (eg. sqrt to √), supports math-like syntax (eg. f(x) = x(2sinx + 3) , estimation of derivatives and integrals, complex numbers, and runs in the browser using WebAssembly.

Congrats! I write calculators myself from time to time, but this sounds very impressive :) How was your experience using webassembly? Any good guides that helped you with that part?

It was actually surprisingly seamless with Rust. "wasmpack" pretty much did it all for me. I added some attributes (well, whatever they're called in Rust) to function and struct declaration to show that bindings should be generated for these things, and from that wasmpack could generate JavaScript bindings! Unfortunately I was slightly limited by some libraries not working with WebAssembly, but I got around that fairly easily.

That’s great to hear - thanks for the insight. And kudos again on a great project, definitely not easy to get all this functionality!

This looks extremely useful, even though currently makes quite a few mistakes, as noted by others. A few features that could be nice:

1) It handles 1 000 000 * 3 just fine, but returns 3000000. So it would be nice if it would format output as 3 000 000 as well for readability. At least as an optional setting (even though I have no idea why someone wouldn't want that).

2) Some way of referencing last result. Often you need to perform operations step by step, when, say, estimating something. So either 10 \n + 20 \n * 3 ..., or just referencing last output like some special variable. I though I could do it more verbosely by just x = 10; x = x + 20 ..., but that gives "Variable references itself."

3) Not sure about this one, since this is not something natural at all, and I don't know what to propose to make it natural (at least without proposing map/filter/reduce and some sort of multi-line inputs). Neither is it a real problem, but it's just something I probably use a calculator most often: simply adding up a dozen of numbers, copied from somewhere as a column. So currently I must first open vim, convert it to and expression bc will handle ( 15 + 21 + 32 ...), and then paste in to bc. With kalk it would be similar. Would be great if one could skip that step since this (I assume) would be a common use-case. But, yeah, I don't have an actual suggestion on how to naturally address that.

These are some great suggestions! I should absolutely make it add spaces, can't believe I didn't think of that.

Also, it actually does have a way to reference the last result, I forgot to document it. It's a variable called "ans"!

The last thing, yeah, that would be neat. I'll think about it...

This is a really great calculator, will definitely be using it! FYI I noticed there is a very similar product with the same name: https://kalk.dev/

Yeah the name isn't very good. This wasn't actually supposed to become something, it was a quick thing I made when I was bored, that suddenly expanded into all this, haha. I like being able to type `kalk` in the terminal, but maybe something needs to be added to the name to make it more recognisable.

"kalk" is a great name for a calculator since the word also means "chalk" in a number of European (and descendant) languages.

Oh haha nice!

Also I noticed it crashes if you write ceil<TAB> then erase the right-most ceil symbol!

> At least as an optional setting (even though I have no idea why someone wouldn't want that).

Copy/pasting? At least each three zeroes could alternate in color, to make it easier to paste the numbers elsewhere.

I usually use the interactive Python prompt when doing calculations, but kalk takes it up a notch. Well done!

(The pre-built Linux binary segfaults before it can show the result on my ArchLinux box, but the cargo installed one works like a charm.)

Thank you! I made this as a replacement for using the Python prompt for calculations actually haha.

Hm that's strange though, it seems to work for me (also on Arch). What calculation did you do?

Any calculation, even simple ones

    >> 1+2
    fish: Job 1, './kalk-linux' terminated by signal SIGILL (Illegal instruction)

Well, that's not a segfault. It's more likely that it's being compiled with an incorrect/specific architecture (e.g. using AVX2 instructions). Though it really shouldn't be using such instructions for basic math. It is possible the instruction pointer is getting messed up too.

Ah, thanks for setting me straight. I just noticed the core dump and assumed a segfault.

And thanks for fixing the two issues so fast.

Hmm, that's very strange, considering I'm running a very similar setup (Arch and fish). I wonder if it could be an issue with the library I'm using for big floats..

I agree, that's very strange, considering the similar enviroments. But perhaps your CPU has a more modern instruction set than mine.

(Same thing happens if the shell is bash.)

`√2` works but `√-1` doesn't, which surprised me a bit. I' expect unary `-` to bind tighter, but in this context it considers that it's a binary operator between `√` and `-1`. If you put parens it works of course.

Yeah same with x^-1, I forgot about that, thanks!

For fun, try to run this: `2 + 2 * 10%` in all calculators you have access to: on you phone, on your desktop, in kalk.

As they say, "the answer will surprise you" :)

  $ units
  You have: 2 + 2 * 10%
    Definition: 2.2
ITYM "the answer may surprise you", and in this case it did not.

I did say "in all calculators you have access too, including kalk" ;)


Performing the calculation with Soulver did not surprise me (being what I calculated in my head ahead of time):

    2 + 2 × 10% = 2.2
At the risk of admitting my ignorance, yet more interested in learning something new: should this answer (2.2) surprise me?

Wolfram Alpha and iOS also give 2.2

On MacOS the answer is 2.4

In kalk it's 2.002

On Windows it's 0.4 in simple calc, and 2 in programmer calc (and there's no % in engineering calc)

2.2 via Google[0]

> and there's no % in engineering calc

Use 0.1 instead of 10%, it has the same vibe ;)

[0] https://www.google.com/search?gbv=1&q=2%2B2%C3%9710%25&oq=&a...

What about the win32 calculator shipped with w7 and w10 ltsc?

Haha damn, didn't expect that

Android gives me 2.2

Is there an explanation for the answer in kalk? Seems buggy

It seems like an expression like "1 * 10%" in kalk is computed as if it means "1% * 10%" => "0.01 * 0.1" => "0.001"

The calculator that comes with MIUI 12 (Xiaomi phone) writes everything as you type, like you'd expect.

But, the moment you type `%`, it instead replaces `10` with `0.1`. So in the end the screen shows: 2+2x0.1 = 2.2

I guess not as surprising as you expected :-]

I did say "in all calculators you have access too, including kalk" ;)


Forth, once using fixed point and scaling 2e+2:

      2 dup 100 10 */ swap 100 * + .S 220 OK

For what it’s worth, my first session went like this:

  >> e^iπ+1
  2.6974097548 + 2.6435590641i
  >> e^iπ
  1.6974097548 + 2.6435590641i
In fairness, I still don’t know where “e” comes from in complex number notation. The transition from cos(angle) + i sin(angle) seems to become “e^i(angle), lol” and no one explains it further. Before I started doing signal processing, I too would have thought that e^i pi is something like 1.69 + 2.64, so it’s correct, in a certain sense. But perhaps not the common mathematical sense.

EDIT: Ah, I see the problem. I suspected that e^iπ was being turned into πe^i incorrectly, but when I typed the open parenthesis for e^() and put my cursor inside it, typing "i" resulted in e^i() rather than e^(i). So it was impossible to parenthesize correctly, and I assumed e^iπ had the usual meaning.

The derivation comes from Taylor series expansion of the exponential function e^x = 1 + x/1! + x^2/2! + x^3/3! + …

You can throw together a program that will show numerically that this both converges to e^x for real x and that e^ix converges to cos(x)+i*sin(x). You can also find proofs online I’m sure.

Why do it numerically? Show that e^ix converges, then you can reorder the sums, grouping the odd and even terms you get series expansions for cos(x) and i sin(x).

You actually have to understand calculus for that to actually prove it to you, but, you can show that it seems to work out numerically with a bit of programming knowledge, which I imagine is more common on Hacker News.

I don't think either the numerical or symbolic proofs really help build intuition though. This video [1] kinda helps, although it glosses over the critical fact "multiplying by i rotates counterclockwise 90°."

[1] https://youtu.be/v0YEaeIClKY

Hmm. This is the second time I've seen that "multiplying by i rotates counterclockwise 90 degrees."

I agree that this is one way to interpret the result. But is it literally equivalent to matrix multiplication by a 2D rotation matrix? Someone tried to say it was, which I felt skeptical about.

(Also, thank you.)

It is literally equivalent to a rotation matrix:

    [cos π/2  -sin π/2] [x] = [0  -1] [x] = [0 - y] = [-y]
    [sin π/2   cos π/2] [y]   [1   0] [y]   [x + 0]   [ x]
Compare to:

i (x + iy) = ix + i²y = -y + ix

For the general case of rotation in the complex plane, multiplying by a complex number with an absolute value of 1 (i.e. on the unit circle) rotates by that number's angle from the positive reals. Normally you'd write such a number as e^iθ, but since that's what we're trying to get to, we can instead write it as cos θ + i sin θ.

    [cos θ  -sin θ] [x] = [x cos θ - y sin θ]
    [sin θ   cos θ] [y] = [x sin θ + y cos θ]
Compare to:

(cos θ + i sin θ) (x + iy)

= x cos θ + ix sin θ + iy cos θ + i²y sin θ

= (x cos θ - y sin θ) + i (x sin θ + y cos θ)

Maybe the cause of your skepticism is that it seems unintuitive that complex numbers, which are 2-dimensional in linear-algebra-speak, could be as powerful as 2×2 matrices, which are 4-dimensional. But keep in mind that 2×2 matrices can perform any linear transformation on 2-dimensional vectors using only matrix multiplication, whereas complex number multiplication can only scale and rotate, and you need to use complex addition to get translation, and I'm not sure off the top of my head if it's possible to get shear transformations using complex numbers.

I just wanted to say, thank you so much for explaining this so thoroughly. I feel much more comfortable using complex numbers now that I allowed myself to believe "it's literally equivalent to a rotation matrix."

(I'm a former gamedev, so rotation matrices are very intuitive. But for some reason, I never made the connection to complex numbers, except in an abstract math-y sort of way.)

@mayfer also tried to explain to me that it was a rotation matrix. This tweet chain was helpful; posting it here in case anyone needs further convincing: https://twitter.com/theshawwn/status/1400591835052056580

Just to be pedantic, the Taylor series definition of the exponential converges absolutely, hence we can reorder the terms by odd/even powers without changing the sum.

It's the exponential notation for complex numbers, see for example https://tutorial.math.lamar.edu/Extras/ComplexPrimer/Forms.a...

That post proves the point: it jumps from "use cos(t) + i sin(t)" to "use e^it" with zero explanation about why it's related to 2.718281828...

The reason I posted my comment is because e^(i pi) is obviously supposed to be -1+0j. But I see now that I was using the calculator incorrectly (I was doing the equivalent of πe^i) but there was a bug in the parenthesis operator preventing me from typing it that way on mobile.

> it jumps from "use cos(t) + i sin(t)" to "use e^it" with zero explanation about why it's related to 2.718281828...

It really isn't, beyond the fact that exp(1) = 2.718…. Then, by definition exp(it) = exp(1)^(it) = e^it. It isn't much more than a notational artifact as far as I'm concerned. For that matter, raising any base b to a power is equivalently just scaling it by ln(b) and plugging it into exponential function, that is, b^it = cos(ln(b) * t) + i sin(ln(b) * t).

That last equation clarified things greatly for me. Thanks.

This is somewhat similar to my project at https://calcula.tech, although the usecase is a bit different. There are a few other calculators around that use Rust + WASM which is kind of interesting

Very cool, I'm building a similar project atm as well (not ready to share, but you could dig it up easily), the latex reprinting of input is an interesting twist that I'm sure many people will appreciate.

I am afraid this domain is a prime nerd-sniping range, because there are so many variations on building a better, more interactive calculator. No profits here besides learning and great fun!

If everybody adds his/her rust+wasm+calculator projects in the comments, let me jump in as well with mine :) https://bbodi.github.io/notecalc3/

Nice work btw!

Can you support big numbers?

When I input 3^4^5, it outputs infinity.

The desktop program does technically have the capabilities of that, but lately I've been focusing a lot more on the web version, that unfortunately doesn't, so results are 64-bit at the moment. I have been waiting for a proper Rust library that can do this, so that it could work on the web version as well, but so far, that has not happened, so I'll probably do some work on properly supporting big numbers on the desktop program soon.

An interactive calculator that passes the 0.1+0.2 test, very nice.

I'm a big fan of https://qalculate.github.io/. It has a nice GUI which can be used interchangeably with the CLI version.

It also has units, many built-in physical constants, currency conversion, matrices and probably tons of other stuff I don't know about.

I don't think it can be easily ran in a browser though.

This seems off:

    >> f(x) = x^2 
    >> f''(4)

Oh yeah, derivatives of higher order being less accurate is a known problem. I forgot to specify that, thanks!

Note that if f(x) = x^2 then the second derivative f''(x) = 2, so it looks like you're off by a factor of 2 (as well as the accuracy issue).

look into Dual numbers. That way there is no accuracy loss. More generally look into AD (automatic differentiation). thanks me later, cheers

Maybe the derivation could be done by the complex step trick, if programing an AD system is too hard

Maybe best to just disable it for now, I played with e^x as well and the results were off as well.

Ignoring these, I really like Kalk!

Thank you! Yeah, or at least give a warning.

Beautiful Web GUI, beautiful source code, "cargo install kalk_cli" && it works like a charm! Thanks for sharing this.

Thank you so much! This is my first (and only) Rust project so I'm a bit nervous about the code quality.

Nice work! And you beat me to the name "Kalk", I've had a private github repo with a calculator with that name for a while, though mine takes sort of the opposite approach, input and manipulation is very visual.

> though mine takes sort of the opposite approach, input and manipulation is very visual.

There is already opensource app for that: microMathematics Plus (μMath+) — Extended visual calculator for Android.[0,1]

[0] https://github.com/mkulesh/micromathematics

[1] https://f-droid.org/packages/com.mkulesh.micromath.plus/

Sure, there's lots of great calculator apps with visual interfaces.

Any interest in adding more symbolic stuff? There often isn't really any reason to do derivatives numerically. While I was looking at the derivatives I noticed the word "quotinent" should be "quotient" in the readme.

I have thought about doing derivatives and such algebraically when possible. It should certainly be doable, and I already have a system for moving things around to achieve these kind of things. This may be a thing in the future.

There are also some algorithms for trying to deal with symbolic integrals but they're pretty intense compared to what you have to do for derivatives (which are very easy).

Yeah that makes sense. I won't be able to do it 100% of course, especially considering I so far have only learned high school maths, but even if it just manages to do it in some situations, that would still be fine as long as it falls back to (often quite accurate) numerical integration. I'll read some more about it!

Would love to have TeX syntax support for this one, as I'm so used to typing it.

This is really nice and all, but what I (and probably many others) would love is an alternative to `bc`. It's so useful but also so limited.

Can you elaborate? I think I know what you mean, but when I clicked the link it already seemed to be a "more advanced bc" to me. What are you missing, big numbers (that's what came to my mind)?

If you're looking for something more advanced while still at the command prompt, check out "calc":


On Fedora:

sudo dnf install calc ; alias bc=calc

what features from bc do you need? Have you seen calc (the calc package in debian/ubuntu)?

Pity it's not in homebrew. I realize I can manually download a binary and manually install it and make a note somewhere where I got it from in case I forget and then periodically re-check manually if an update is out, or just never install any updates, but I'm trying to not do that if it can be helped.

Yeah maybe it should be on homebrew and other package managers. Didn't actually expect it to get this much attention! I'll see what I can do

Kudos to the author, it seems a very nice calculator program.

Any chance in the future that Kalk will support quaternion numbers[1]?


Can you give an example of a quaternion computation that would be useful in a calculator? I would imagine that quaternions and GA are best suited to have a graphical output, ala https://enkimute.github.io/ganja.js/examples/coffeeshop.html ?

Thank you.

Oh my... aren't those really complicated? Haha

You can operate on them using the same rules as complex numbers with a slight twist.

ah beautiful, i was hoping a cli-ified/updated version of the already wonderful OpalCalc would come into existence!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact