Hacker News new | past | comments | ask | show | jobs | submit login

On my linux box:

    $ echo "(2/3)*3-2" | bc -l
    -.00000000000000000002



In the terminal I always use “dc”, where, besides being RPN, you have to explicitly set the precision. I.e. the result of 2∕3 (or “2 3 /”) in dc is always ”0” unless you set a precision beforehand. This makes it clear that the result is arbitrary.


bc and dc are arbitrary precision. By using -l you are specifying that it should keep track of 20 decimal digits (plus you are importing some extra stuff).

You can try higher precision by setting the scale.

    $ echo "scale = 100; (2/3)*3 - 2" | bc 
    -.000000000000000000000000000000000000000000000000000000000000000000\
    0000000000000000000000000000000002


a neat calculator is spigot. It has no trouble getting exactly 0 for this calculation:

    $ spigot '(2/3)*3-2'
    0
furthermore, when you specify a precision number, this sets the precision of the final result, NOT the precision of intermediaries (which is what bc & dc, and many other arbitrary precision calculators do); every printed digit is correctly rounded. [edited to add: truncated towards zero by default; other rounding modes available as commandline flag]

    $ spigot -d72 'sin(1)-cos(1)'
    0.301168678939756789251565714187322395890252640180448838002654454610810009
There are still conditions where spigot can't give an answer, such as

    $ spigot 'sin(asin(0.12345))'
.. spigot can never determine the next correctly rounded digit after "0.1234" with certainty, for reasons elucidated in the documentation.

spigot is in debian and here's the author's page with links to a lot more background: https://www.chiark.greenend.org.uk/~sgtatham/spigot/


> spigot can never determine the next correctly rounded digit after "0.1234" with certainty, for reasons elucidated in the documentation.

Because spigot rounds towards zero in that mode, and it can only bound the result as arbitrarily close to 0.12345 - i.e., it can never decide between 0.12344999..99something and 0.12345000..00something because the "something" part that might break the tie never appears. This is a general issue with exact real computation; in more complicated cases, it can even be undecidable whether some expression is exactly zero.


Stuff like this is why I use Python for basic math

On my phone:

    ~ $ python -c "print( (2 / 3) * 3 - 2 )"
    0.0
    ~ $ python --version
    Python 3.11.5


why not pipe the input through a few more commands? :-P

    bc -l -e "(2/3) * 3 - 2"


I don't know which system you're on, but GNU bc does not support this flag.

On the other hand, bash and zsh support this:

  bc -l <<<'(2/3) * 3 - 2'
edit: neither does busybox.


Huh. I assumed I was on standard versions of these kind of really old utilities. But you're on to something:

    bc -v
    bc 4.0.2
    Copyright (c) 2018-2021 Gavin D. Howard and contributors
    Report bugs at: https://git.yzena.com/gavin/bc


Like this?

$ echo "(2/3)*3-2" | bc -l > /dev/null && echo "0"


First prize would be if you could write a pipe which meaningfully combines bc, cc, dc, fc, nc and wc. No other commands allowed.




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

Search: