The exact function is already implemented in aluFunctions.cc, but currently it has an incorrect implementation that returns zero (false) for every call. This is better than returning 1 (for true), but we'd like to get the correct answer.
So this is how it should work: The function should return true (1) when the operand expression is evaluated exactly, and zero when it is not - usually because it it rounded up. For example:
$ specs print "2+2"
4
$ specs print "exact(2+2)"
1
This is because 2+2 is exactly equal to 4. Similarly,
$ specs print "20//3"
6
$ specs print "exact(20//3)"
1
Because the integer division of 20 by 3 yields 6. However,
$ specs print "20/3"
6.66666666666667
$ specs print "exact(20/3)"
0
because the real division of 20 by 3 is six and two thirds - the resulting float is rounded up a little.
This is the simplest case. With more complex operations, you usually get a non-exact result every time one of the operands is non-exact. For example:
$ specs print "20/3+4"
10.66666666666667
$ specs print "exact(20/3+4)"
0
But there are exceptions:
$ specs print "(20/3)*0"
0
$ specs print "exact((20/3)*0)"
1
Because the multiplication by zero makes the result exact.
It's always better to err on the side of returning false, and only returning true when we are sure that the answer is exact.
Other things to think about system counters, field identifiers, functions, persistent variables
System counters
System counters are internal variables set through the SET spec unit. They also have to be either exact or inexact as they are used in expressions. For example:
$ specs SET "#0:=20/3" print "exact(#0)"
0
$ specs SET "#0:=2+2" print "exact(#0)"
1
Field identifiers
Field identifiers are internal variables identified by letters that do not persist from line of input to the next, but they are read from input lines:
$ specs WORD 1 a: print "exact(a)"
1
$ specs WORD 1 a: print "exact(a+20/3)"
0
We have to consider the input as exact.
Functions
Some functions return exact values; some functions return inexact values; some return exact or inexact values based on the input. And we have two kinds of functions - the built-in functions and the Python functions written by the user. The answer to the question of whether the value returned by the function is exact or not has to be considered on a per-function basis.
To reduce the scope of the solution to this issue, I suggest that for now we consider the output of Python functions to be non-exact. We will revisit this in a future version. To be determined if we want in this release a mechanism for classifying the built-in functions.
Persistent variables
These are variables stored persistently through the pset and pget functions. As the specification doing the pget has no idea what the function doing pset had done, we'll treat then as inexact.
The
exactfunction is already implemented inaluFunctions.cc, but currently it has an incorrect implementation that returns zero (false) for every call. This is better than returning 1 (for true), but we'd like to get the correct answer.So this is how it should work: The function should return true (1) when the operand expression is evaluated exactly, and zero when it is not - usually because it it rounded up. For example:
This is because 2+2 is exactly equal to 4. Similarly,
Because the integer division of 20 by 3 yields 6. However,
because the real division of 20 by 3 is six and two thirds - the resulting float is rounded up a little.
This is the simplest case. With more complex operations, you usually get a non-exact result every time one of the operands is non-exact. For example:
But there are exceptions:
Because the multiplication by zero makes the result exact.
It's always better to err on the side of returning false, and only returning true when we are sure that the answer is exact.
Other things to think about system counters, field identifiers, functions, persistent variables
System counters
System counters are internal variables set through the
SETspec unit. They also have to be either exact or inexact as they are used in expressions. For example:Field identifiers
Field identifiers are internal variables identified by letters that do not persist from line of input to the next, but they are read from input lines:
We have to consider the input as exact.
Functions
Some functions return exact values; some functions return inexact values; some return exact or inexact values based on the input. And we have two kinds of functions - the built-in functions and the Python functions written by the user. The answer to the question of whether the value returned by the function is exact or not has to be considered on a per-function basis.
To reduce the scope of the solution to this issue, I suggest that for now we consider the output of Python functions to be non-exact. We will revisit this in a future version. To be determined if we want in this release a mechanism for classifying the built-in functions.
Persistent variables
These are variables stored persistently through the
psetandpgetfunctions. As the specification doing thepgethas no idea what the function doingpsethad done, we'll treat then as inexact.