11

I just found a good command line calculator program called bc and was satisfied with it until I discovered it rounds off fractional values, thus causing loss in precision.

According to its man page:

All numbers are represented internally in decimal and all computation is done in decimal. (This version truncates results from divide and multiply operations.)

Could you please suggest an equivalent of bc for Ubuntu Maverick? I need to make advanced command line calculations with variables.

muru
  • 207,228
sergionni
  • 523

9 Answers9

13

You can set the length of the fractional part with scale=n.

The command echo 'scale=20;752/447' | bc yields:

1.68232662192393736017

Note that even if the number fits within the scale, additional zero's might be appended:

scale=20
1/2
.50000000000000000000

Unfortunately, there is always a rounding issue:

scale=50
1/3*3
.99999999999999999999999999999999999999999999999999
Lekensteyn
  • 178,446
11

calc (I believe from package apcalc) does the same as bc, but does not round. It displays similarly to bc, but unlike bc, it understands scientific notation. Example:

> calc
C-style arbitrary precision calculator (version 2.12.3.3)
Calc is open software. For license details type:  help copyright
[Type "exit" to exit, or "help" for help.]

; a=234
; b=a/7
; b
    ~33.42857142857142857143
; c=b/1e20
; c
    ~0.00000000000000000033
; c*1e10
    ~0.00000000334285714286
; 

Compare with bc:

> bc -l
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
a=234
b=a/7
b
33.42857142857142857142
c=b/10^20
c
.00000000000000000033
c*1e10
(standard_in) 6: syntax error
c*10^10
.00000000330000000000

A little search turns up lots of results, not all of which are relevant, but I am sure that a few trials will get you exactly what you want (wcalc, for instance):

aptitude search calc
i   apcalc                               - Arbitrary precision calculator (original name: calc)
i A apcalc-common                        - Arbitrary precision calculator (common files)
p   apcalc-dev                           - Library for arbitrary precision arithmetic
p   bandwidthcalc                        - file transfer time calculator written in GTK+
p   calcoo                               - Scientific calculator (GTK+)
p   calcurse                             - text-based calendar and todo manager
p   concalc                              - console calculator
p   extcalc                              - multifunctional scientific graphic calculator
p   gcalcli                              - Google Calendar Command Line Interface
i   gcalctool                            - GNOME desktop calculator
p   ipcalc                               - parameter calculator for IPv4 addresses
p   ipv6calc                             - small utility for manipulating IPv6 addresses
p   kcalc                                - calculator for KDE 4
p   keurocalc                            - universal currency converter and calculator - binary package
p   keurocalc-data                       - universal currency converter and calculator - data package
p   lcalc                                - a program for calculating with L-functions
p   libcolor-calc-perl                   - Perl module for simple calculations with RGB colors
p   libdate-calc-perl                    - Perl library for accessing dates
p   libdate-pcalc-perl                   - Perl module for Gregorian calendar date calculations
p   libmath-basecalc-perl                - Convert numbers between various bases
p   libmath-calc-units-perl              - Human-readable unit-aware calculator
p   libmath-calculus-differentiate-perl  - Algebraic Differentiation Engine
p   libmath-calculus-expression-perl     - Algebraic Calculus Tools Expression Class
p   libmath-calculus-newtonraphson-perl  - Algebraic Newton Raphson Implementation
p   libticalcs-dev                       - Texas Instruments calculator communication library [development files]
p   libticalcs2-7                        - Texas Instruments calculator communication library
p   libwww-google-calculator-perl        - Perl interface for Google calculator
p   octave-physicalconstants             - provide physical constants values in Octave
i   openoffice.org-calc                  - office productivity suite -- spreadsheet
v   openoffice.org2-calc                 -
p   python-ipcalc                        - perform IP subnet calculations
v   python2.6-ipcalc                     -
p   r-cran-epicalc                       - GNU R Epidemiological calculator
p   rpncalc                              - RPN calculator trying to emulate an HP28S
p   science-numericalcomputation         - Debian Science Numerical Computation packages
p   sipcalc                              - Advanced console-based ip subnet calculator
p   subnetcalc                           - IPv4/IPv6 Subnet Calculator
p   sugar-calculate-activity             - calculate activity for the Sugar graphical shell
p   tapecalc                             - a full-screen tape editor that lets the user edit a calculation
p   transcalc                            - microwave and RF transmission line calculator
p   wcalc                                - A flexible command-line scientific calculator
p   wmcalclock                           - A dock.app which simply tells time and date
p   xsmc-calc                            - Smith Chart calculator for X
10

I would suggest using Python as a command-line calculator:

$ python
>>> from math import *
>>> help(sin)
    sin(x)

    Return the sine of x (measured in radians).

Also I would recommend IPython or IDLE. Both hugely improve usability of the standard shell.

Update: use python3 to avoid truncation surprises:

$ python2.7

>>> 10/3
3

$ python3

>>> 10/3
3.3333333333333335
antimirov
  • 211
6

You lost precision in this sense: if set precision to 10 decimal digits, divisions are truncated to 10 decimal digits, and this is a coherent choice.

If you look for an exact calculator, you need a symbolic system as maxima.

By the way, bc supports variables.

enzotib
  • 96,093
5

"genius" is the most advanced calculator out there, with both command-line and GUI options available. Check the manual for details, and see http://www.jirka.org/genius.html .

To install, just type:

sudo apt-get install genius gnome-genius
1

Here is a good one:

spigot -- a command-line exact real calculator

Fabby
  • 35,017
Jens_G
  • 11
1

If you have octave installed you can use it at the command line as:

octave --silent --eval 752/447

To shorten the writing you can add the following as alias in .bashrc

alias ose='octave --silent --eval'

and then call it as ose 752/447. The alias/shortcut is arbitrary but you need to restart the terminal to make it effective.

You can install octave using:

sudo apt-get install octave

Of course, with octave you can use all the advanced functions available in it too.

Harris
  • 2,588
1

I just made a simple one:

https://github.com/jb55/ratio-cli

$ ratio <<< '14/15 * 3'
14/5 
0

Tweaks for using python as a calculator are used in my package calcpy.

What it basically does is using IPython's hooks to change any occurence of a number to sympy's Rational:

import ast
from sympy import Rational, init_printing

class ReplaceFloatWithRational(ast.NodeTransformer): def visit_Constant(self, node): if isinstance(node.value, float): return ast.Call(func=ast.Name(id='Rational', ctx=ast.Load()), args=[ast.Call(func=ast.Name(id='str', ctx=ast.Load()), args=[node], keywords=[])], keywords=[]) return self.generic_visit(node)

class ReplaceIntegerDivisionWithRational(ast.NodeTransformer): def visit_BinOp(self, node): def is_integer(x): if isinstance(x, ast.Constant) and isinstance(x.value, int): return True if isinstance(x, ast.UnaryOp) and isinstance(x.op, (ast.USub, ast.UAdd)): return is_integer(x.operand) if isinstance(x, ast.BinOp) and isinstance(x.op, (ast.Add, ast.Sub, ast.Mult, ast.Pow)): return is_integer(x.left) and is_integer(x.right) return False

    if (isinstance(node.op, ast.Div) and is_integer(node.left) and is_integer(node.right)):
        return ast.Call(func=ast.Name(id='Rational', ctx=ast.Load()),
                        args=[node.left, node.right], keywords=[])
    return self.generic_visit(node)

get_ipython().ast_transformers.append(ReplaceFloatWithRational()) get_ipython().ast_transformers.append(ReplaceIntegerDivisionWithRational()) init_printing()

Example:

In [1]: 1/2 + 2/3
Out[1]: 7/6

This would convert all numbers to fractions, on calcpy numbers are printed both as fractions and as decimals.

idanp
  • 101