Of course. Sorry. The code instances I found (e.g. in the Metagol robots example) use X/Y with X and Y bound at runtime and and I just replaced X and Y with (negative) integers without noticing this particular case is a syntax error. I agree that using (-)/2 for pairs have advantages. But we’re looking for existing codebases that make us of A/B terms.
pmoura:
But we still disagree on choosing this representation
I fear we won’t. A flag gives the option.
[/quote]
I would very much prefer a single (no clashing) representation and no flags at all.
Yes. Thanks for searching. It turns out they exist. It doesn’t convince me that 1/3 is wrong though. It is still the notation any mathematician uses as well as most programming languages that support rationals and it gives exactly the same problems as -2, so we can get used to them. Best, it is easy to write some tooling to find possible problems.
In general I agree. The flag based [97,98,99] vs [a,b,c] strings are a nightmare as two pieces of code that need to cooperate cannot disagree. That is not the case here. On module can use 1/3 and the other 1R3 and if we allow for a character as syntax, a third can use 1_3 and they can happily exchange rational numbers. The last is attractive as it allows running ECLiPSe code that uses rational numbers unmodified.
Note that by using / you can, with some care, write code using rationals on SWI to run on a Prolog system without rationals. Using 1R3 that is no option. Using 1r3 it would be, but then we have another potential compatibility issue. I’m quite sure some program will break, though not many.
On a module level I tend to agree. But variations complicate general discussions, e.g., what do I mean by 1/3 when used in isolation. It creeps into documentation - what should be used in quoting queries or code snippets. And it complicates reading other peoples code if their convention is not what I usually use (particularly if it’s 1/3).
So at least having a dominant, unambiguous syntax for general use, e.g., 1r3 or similar, is very helpful. By all means have a definable character (including / or _ or whatever) for use inside a module for code portability, but the dominant syntax should be the default IMO. Those who choose something else should be made aware of the consequences - it’s not just about their code.
Got to an agreement with ECliPSe and pushed a commit that implements this. Bottom line:
The canonical syntax for rationals is e.g., 1r3. This is read by SWI-Prolog in any mode (if rationals are supported) and always written by write_canonical/1,2.
In addition ECLiPSe reads 1_3, but will write 1r3.
SWI-Prolog keeps supporting 1/3 input and output using the flag rational_syntax as natural.
I think this settles how rationals work in SWI-Prolog. The current implementation and documentation should be complete, but is not very well tested.
It is IMO a bad idea. You start with something precise, then some operation is fuzzy because it can only be done as floating point and then the float is converted implicitly back to rational, so you think the result is precise, but it isn’t. I think that is not acceptable.
I think you should have gotten an idea about the release structure of SWI-Prolog. There are devel releases about every couple of weeks, depending on progress and stability. There is a daily build for Windows from the master branch at approx 4.30AM (CET) if it builds. Anyone on other platform should setup compilation from (git) source or wait for the next release. Depending on the platform it takes between a few minutes (Linux), half an hour (MacOS, depending whether or not you already have Xcode and Macports) and some real dedication (Windows) to setup compilation from source
Just opened on issue on this. SWIP uses the GMP library to implement rational numbers. It’s functions which convert rationals (and big ints) to floats truncate (round to zero) if necessary and, apparently, sometimes when it’s not even necessary.
The answer is low by 1 ULP:
?- X is float(31415r10000),N is nexttoward(X,inf).
X = 3.1414999999999997,
N = 3.1415.
The problem is compounded when the rounding mode is to_positive or to_negative depending on the sign of the argument.
I believe sqrt is one of those functions that is defined to always return a (positive) float. The transcendental functions, exp, log, etc are similar, e.g., 1.0 is exp(0), 0.0 is sin(0). The other side of the coin is that the value of an expression will be converted to a float whenever you use one of these functions, which is usually what you want. (There’s probably a good reason why the GMP library provides such a limited set of mathematical functions.)
I think the only functions that preserve precision when possible are the basic arithmetic functions (+,-,*,/,**). (And ^, being a synonym for **). As a consequence, 4*1r2 is not the same as sqrt(4) although they may be arithmetically equivalent.
Yes, all the GMP convert to double functions have the same issue (round towards zero). This affects both big integer and rational number conversion. In fact, it’s documented behaviour on the GMP web site.
Note that “nearest” isn’t the right answer either. It should adhere to whatever rounding mode is currently set, which is usually nearest.
But any conversion is only guaranteed to be within 1 ULP (plus or minus). If that’s the case using =:= may not always succeed, depending on the value.
One solution (which I suggested in the issue filed on github) is to wrap all GMP conversions with a function that uses the current rounding mode and nexttoward to compensate. I doubt GMP will change.
Joachim and I decided non-decimal rational numbers are out. If someone comes with a sufficiently convincing case where they are useful we can always reconsider.
As for #, it is a free world. Single letter textual operators are fairly uncommon though, but the limited set of symbol character is frequently used as operator and I’d consider that a bit risky.