Personal Calculator .NET
A programmer's calculator for the Windows programmer
Abstract
When I started the Personal Calculator .NET project ("bpc") I did it for myself. I wanted a good, easy to use text-mode calculator for Windows that didn't require
that I install a new software package, that was stateful, extensible, and easy to maintain, and that did all of the things I wanted it to. That last goal is still
a work in progress, but so far bpc is everything that I have dreamed it up to be. Throughout the development process I utilize common design patterns to ensure simplicity
in the code and to make it easy to maintain and add new features to it. When it comes down to it, I have almmost created a new programming language, and some of the
constructs and syntax resemble programming languages. Why is this? This is because I am a programmer. I crafted this piece of software for my own use, and I hope that
others will find it useful also.
From PC to BPC
Bpc is a living project. It has had many incarnations. In fact it started out in Java, simply because that was the language I knew best at the time. With my heavy
immersement in C# over the last year I decided that re-developing it in .NET would be a step in a good direction. Since my target platform has been Windows all along
(primarily because Linux and UNIX OSs already have comparable software) .NET was a good choice for programming platform. I have tried many techniques for programming
it, from separating the entire user-input expression into an array of chars in order to reconstruct tokens that were recognized as numbers or
operators, to relying on regular expressions to extract sub-expressions from a whole expression, to utilizing regular expressions to recognize tokens and parse them
from the expression string. While all of these incarnations of bpc resulted in a similar product externally, their interior changed drastically on each attempt. Some
attempts worked very well, while other failed miserably either in maintainability, reliability, or performance.
Bpc code currently uses several well developed, well-known design patterns, such as TryParse, Decorator, and State. Everything in bpc is programmed to an interface as
much as possible. There continue to be areas that need re-factoring, and as needed I will refactor them. I currently have some milestones set in place for continued
development. I will add these enhancements as time goes on, and as I find that I need them. If anybody using bpc find in urgency that they desire these or any other
features to be added to bpc, feel free to add a feature request on SourceForge.net or contact me personally.
How to Use BPC
I have developed bpc to be used in two ways.
- Interactively
- On the Command-line
An interactive, stateful calculator was my initial goal, while the command-line interface, although an afterthought, occurred to me as a useful feature, and thus I went
to work on making it useful. The test script included with the binary download utilizes the command-line interface entirely. Both interfaces use exactly the same code paths
aside from the initial figuring out whether to use command-line or interactive mode.
Online Help
Online help is included as a feature of bpc. You may invoke it from the command-line by typing:
PS C:\> bpc --help
If you are in interactive mode, you may invoke the online help system by typing:
>>> ?
Both produce the same output. The same functionality is available for both modes.
Supported functionality:
Decimal numbers; hexadecimal numbers ending with h, octal numbers ending with o, binary numbers ending with b.
Arithmetic operators: +, -, *, /
Binary operators: & (and), | (or), ^ (xor)
Boolean operators (not chainable): ==, <=, >=, !=
Functions: ** (power), // (div), % (mod), ! (factorial), cos, acos, cosh, sin, asin, sinh, tan, atan, tanh, sqrt, log (base-
10), ln, lb (ld|lg, base-2)
Conversion: toh (hex), tod (dec), tob (bin), too (oct), deg, rad
Constants: pi, e, $ (last result)
Parentheses: (, )
Expression delimiter: ; (separate multiple expressions on teh same line)
Variables: assignment using =, inline usage, names must begin with underscore (_)
Bpc also has a couple of other command-line arguments. Two of them affect the context, and the other two display information about bpc.
- --mode-degrees, sets the trigonometry mode to degrees.
- --mode-radians, sets the trigonometry mode to radians, which is the default mode.
- --version, displays the assembly version of bpc.
- --license, displays licensing information pertaining to bpc.
Here is a run-down of the rest of the functionality. The remainder of my examples will be shown as it would look in interactive mode. To get bpc into interactive mode, simply type bpc in your terminal (cmd.exe or PowerShell usually.)
Arithmetic Operators and Perentheses
You may use +, -, *, /, (, and ) as you would expect to use them on any other calculator system. For example:
>>> 14 + 7
21
>>> 36 - 12
24
>>> 5 * 6
30
>>> 81 / 9
9
>>> (19 + 1) / 10
2
>>> 19 + 1 / 10
19.1
As you can see order of operations is also observed, like in the last example division has higher precedence than addition, so it is evaluated first.
Trigonometric and Algebraic Functions
The following trigonometric and algebraic functions are currently supported by bpc:
- **, which is power, for example two squared would look like: 2 ** 2.
-
//, which is divmod, for example to get the whole part of a division operation that would return a fractional result like 10 / 8, you would type: 10
// 8, and that would result in 1.
- %, which is modulus or remainder. Similar to the above example you would type: 10 % 8 and get 2
-
!, which has two meanings, dependent upon whether it appears before or after an expression. The algebraic meaning comes after an expression as in six
factorial or 6!, which would result in 720
- cos, acos and cosh which are cosine, arc- or inverse cosine, and hyperbolic cosine, used like cos(pi), acos(pi) or cosh(pi)
- sin, asin which are sine, arc- or inverse sine, and hyperbolic sine, used like sin(pi), asin(pi) or sinh(pi)
- tan, atan which are tangent, arc- or inverse tangent, and hyperbolic tangent, used like tan(pi), atan(pi) or tanh(pi)
- sqrt, which is square root, used like: sqrt(25), which would result in 5.
- log, which is base-10 logarithm, used like log(10), which would result in 1.
- ln, which is natural logarithm, used like ln(e), which would result in 1.
- lb, ld, or lg, which are all synonyms for binary logarithm, used like lb(2), ld(2), or lg(2), which all result in 1.
- deg, which converts a value to degrees.
- rad, which converts a value to radians.
>>> 2 ** 2
4
>>> 10 // 8
1
>>> 10 % 8
2
>>> cos(pi); acos(pi); cosh(pi)
-1
NaN
11.5919532755215
>>> sin(pi); asin(pi); sinh(pi)
3.23108510433268E-15
NaN
11.5487393572577
>>> tan(pi); atan(pi); tanh(pi)
-3.23108510433268E-15
1.26262725567891
0.99627207622075
>>> sqrt(25)
5
>>> log(10)
1
>>> ln(e)
1
>>> lb(2); ld(2); lg(2)
1
1
1
>>> tan(rad(45))
0.999999999999999
Mathematical Constants
Two common mathematical constants are also provided, PI and E. Since bpc is not case-sensitive, you may type either PI or pi to represent
the mathemetical constant named PI. Bpc interprets PI and E as numbers and so they can be used in any way that a normal number may be used in an
expression. You can even use them alone. Currently bpc uses the types double and long for floating-point and integer calculations, so their limits
are set based on the limit of these value types. As a result both PI and E are only interpreted out to 14 decimal places.
>>> pi
3.14159265358979
>>> e
2.71828182845905
Binary Operators
Binary operators are supported for both boolean and numeric values. The following binary operators are supported:
- &, which is binary AND.
- |, which is binary OR.
- ^, which is binary XOR or exclusive OR.
- !, which is binary NOT. In this case the ! operator must come before a mathematical expression to be interpreted as binary NOT. Binary NOT will cause true to be false, a positive number to become negative, or a negative number to become positive.
>>> 100101b & 001100b
100b
>>> 100101b | 001100b
101101b
>>> 100101b ^ 001100b
101001b
>>> !true
false
>>> !24
-24
Boolean Operators (Conditional Operators)
Boolean, or conditional operators as they are known to many in programming languages, may be used either with numeric values or with boolean
values, but not both. Either way the result of both sides of a boolean expression must be boolean or numeric in order to be valid. Chaining of
boolean expressions is possible using a variable and binary expressions. For example, say you wanted to express 5 <= 6 == (2 * 3). Here is
how you would accomplish this:
>>> _var = 6; (5 <= _var) & (_var == (2 * 3))
6
true
Below is a listing of supported boolean operators.
- ==, equal to.
- !=, not equal to
- <=, less than or equal to, only supported by numeric boolean expressions.
- >=, greater than or equal to, only supported by numeric boolean expressions.
- <, less than, only supported by numeric boolean expressions.
- >, less than, only supported by numeric boolean expressions.
In the order of operations, boolean expressions are evaluated last, so the following is valid:
>>> 24 == 8 * 5 - 16
true
>>> true == true
true
>>> true != true
false
>>> 24 <= 19
false
>>> 24 >= 19
true
>>> 24 < 96
true
>>> 24 > 96
false
Different Number Formats
Bpc supports four different number formats also called bases: decimal, hexadecimal, octal, and binary. Only decimal, or base-10 numbers, may have a decimal
point. Hexadecimal, octal, and binary numbers must be suffixed with a base identifier: h for hexadecimal, o for octal, and b for binary. Here are some
examples:
>>> 13h
13h
>>> 10o
10o
>>> 10110b
10110b
Along with the different number formats is the ability to convert end results to different number formats using the following functions:
- tod, convert to decimal, used like tod(13h).
- toh, convert to hexadecimal, used like toh(24).
- too, convert to ocatl, used like too(1011b).
- tob, convert to binary, used like tob(19o).
Conversion functions may be used with any number format. Numbers are always stored as decimal values. Also the last (by precedence) base used in an expression
is the base that the result of an expression will be output in. For example:
>>> 13h + 24 - 12o * 11b
1101b
>>> tod($)
13
Last Result Constant, Multi-expression and Implied Last Result
In the last section I used $. What is $? It is a special constant that remembers the last result and stores it. You can use it like the other constants, PI and
E. It can store either a boolean or numeric value, and you must be careful to ensure that you use it properly.
Bpc has support for multiple expressions on a single line. You accomplish this by separating each expression with a semi-colon. The result of each expression
will be output on a separate line. In command-line mode multi-expression expressions are sensitive to the current context, which is out of scope after the
command-line operation is completed. In interactive mode the scope of the context is continual until you quit. This means that you can write multi-expressions
like:
>>> 2 ** 3; $ / 8
8
1
You can also imply the last result constant by simply ommitting it. The default value for the last result constant is always zero when the context is new. For
example the above multi-expression could have been entered like:
>>> 2 ** 3; / 8
8
1
in this case, ommitting the $ constant.
Variables are supported in this latest version. Variable names must begin with an underscore (_) and contain only letters, digits, and underscores. Variables can currently be used in two ways: in assignment expressions, and as constants in expressions.
Here is an example of how to use variables:
>>> _sideA = 24; _sideB = 13; sqrt((_sideA ** 2) + (_sideB ** 2))
24
13
27.2946881279124
BPC Tests in PowerShell
Bpc comes with a script that contains tests for it written in PowerShell. Below is an example of a passing test suite.
BPC Tests - PC.NET
This script comprises a series of tests to be run against BPC - Better Personal Calculator.
This script's version is 2.0 and should be used against builds 1.3.0.0 and higher of BPC.
Current version of PC.NET is 1.3.2.0
Running command-line test suite for PC.NET...
bpc <expression> = expected (actual)...Pass or Fail
bpc e # Constant E = 2.71828182845905 (2.71828182845905)...Passed
bpc pi # Constant PI = 3.14159265358979 (3.14159265358979)...Passed
bpc 1 + 2 + 3 + 4 + 5 # Simple Addition = 15 (15)...Passed
bpc 15 - 1 - 2 - 3 - 4 - 5 # Simple Subtraction = 0 (0)...Passed
bpc 13 / (1 / 2) # Simple Division = 26 (26)...Passed
bpc 6 * 8 * 2 # Simple Multiplication = 96 (96)...Passed
bpc (12 + 2) * 6 / 7 - 3 # Arithmetic = 9 (9)...Passed
bpc cos(pi) # Trigonometry - Radians = -1 (-1)...Passed
bpc --mode-degrees tan(45) # Trigonometry - degrees = 1 (1)...Passed
bpc --mode-degrees atan(1) = 45 (45)...Passed
bpc 237 % 15 # Algebra - Modulus = 12 (12)...Passed
bpc 237 // 15 # Algrebra - DivMod = 15 (15)...Passed
bpc 6! # Algebra - Factorial = 720 (720)...Passed
bpc log(pi) # Algebra - Logarithm, base-10 = 0.497149872694133 (0.497149872694133)...Passed
bpc ln(pi) # Natural Logarithm = 1.1447298858494 (1.1447298858494)...Passed
bpc lb(pi) # Binary Logarithm, Base-2 = 1.65149612947232 (1.65149612947232)...Passed
bpc rad(45) # To Radians = 0.785398163397448 (0.785398163397448)...Passed
bpc deg(0.785398163397448) # To Degrees = 45 (45)...Passed
bpc sqrt(25) # Square Root = 5 (5)...Passed
bpc fh + ch # Hexadecimal = 1bh (1bh)...Passed
bpc 10o - 7o # Octal = 1o (1o)...Passed
bpc 1001b + 101b # Binary = 1110b (1110b)...Passed
bpc toh(24) # Conversion - To Hex = 18h (18h)...Passed
bpc too(24) #Conversion - To Oct = 30o (30o)...Passed
bpc tob(24) # Conversion - Binary = 11000b (11000b)...Passed
bpc tod(18h) # Conversion - To Dec = 24 (24)...Passed
bpc -(13 + 19 * 2) # Negative Distribution = -51 (-51)...Passed
bpc !13 + 19 * 2 # Binary NOT = 25 (25)...Passed
bpc 1001b ^ 110b # Binary XOR = 1111b (1111b)...Passed
bpc 110b | 1b # Binary - OR = 111b (111b)...Passed
bpc true | false # Boolean = true (true)...Passed
bpc true != false # Boolean Conditional = true (true)...Passed
bpc false == false # Boolean Conditional = true (true)...Passed
bpc 24 > 13 # Numeric Conditional = true (true)...Passed
bpc 19 <= 20 # Numeric Conditional = true (true)...Passed
bpc 2 != (4 / 2) # Conditional Expressions = false (false)...Passed
bpc 2 ** 3 # Algebra - Power Function = 8 (8)...Passed
bpc 13 ** 2; / 12 # Multi-expression and Implicit Last Result = 169 14.0833333333333 (169 14.0833333333333)...Passed
bpc 13 ** 2; $ # Last Result, $ = 169 169 (169 169)...Passed
bpc 2 ** 2; **2; **2 # Multi-expression and Implicit Last Result = 4 16 256 (4 16 256)...Passed
bpc _var = (13 * 2); 12 ** 2; $ + _var # Multi-expression and Variables = 26 144 170 (26 144 170)...Passed
bpc _myNumber = 18; _myNumber # Variables = 18 18 (18 18)...Passed
Tests completed.
42 tests were run.
42 tests passed.
0 tests failed.
Future Roadmap
- Single result from multi-expressions operator
- Range token and expression
- Matrix token and expression
- User-definable functions
Vocabulary Guide
-
char
-
The term char is a keyword in most programming languages and represents a native or value type that represents a single character. A character may be Unicode or ASCII
by nature.