Whats the hardest part of rational numbers?
Some challenge is surely this identity:
/* for any X and Y, Y =\= 0 and X/Y in float range */
float(X rdiv Y) =:= X/Y
Ether float/1 might defect or (/)/2 might
defect or both. My system is no better,
but I havent released the new rational number
support yet. Here is what can go wrong:
SWI-Prolog (threaded, 64 bits, version 8.1.22)
?- X is 363692165478669/6325070415853456823515
4795849661658452986453051294411986531674383571
9811149985459037376199066991014047459618325990
0372230931523043306046152094168748148078435047
4195086426987926395908669404130106637427399522
7328339256273385702164683181572986403623613565
0314266011211548510419206725953204130822734645
187695728365866909171712.
?- X is float(363692165478669 rdiv 63250704158
5345682351547958496616584529864530512944119865
3167438357198111499854590373761990669910140474
5961832599003722309315230433060461520941687481
4807843504741950864269879263959086694041301066
3742739952273283392562733857021646831815729864
0362361356503142660112115485104192067259532041
30822734645187695728365866909171712).
X = 5.750009747987844e-308.
A tamer goal could be to only have this
axiom satisfied, for rational/1 output:
/* for any X and Y, Y =\= 0 and X/Y in float range,
and XrY result from rational(F) for some float */
float(X rdiv Y) =:= X/Y
Am Montag, 3. Juli 2017 23:14:04 UTC+2 schrieb Mostowski Collapse:
> Dear All,
>
> If you want rational arithmetic(*), and you do the following:
>
> ?- A is 4 rdiv 1/3.
> A = 1.3333333333333333.
>
> This is anyway wrong. What you need to do is:
>
> ?- A is (4 rdiv 1) rdiv 3.
> A = 4 rdiv 3.
>
> Richard O'Keefe idea is already realized, you don't need to do anything anymore, since rdiv/2 is not only a constructor but also an operation, you can do the following, try it for yourself with SWI-Prolog:
>
> Welcome to SWI-Prolog (threaded, 64 bits, version 7.5.8)
> SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
>
> ?- X is (1 rdiv 4) rdiv (1 rdiv 2).
> X = 1 rdiv 2.
>
> ?- X is (1 rdiv 2) rdiv (1 rdiv 4).
> X = 2.
>
> So if you use rdiv/2 instead of (/)/2 you program runs rationals and not floats. I don't see any possility to merge rdiv/2 and (/)/2 into one operator, this is impossible I guess. Now putting side by side the division and the power operator, we could require:
>
> Datatype Approach:
> ============
> datatype division power
> float: (/)/2 (^)/2
> rational: (rdiv)/2 (^)/2 /* name clash */
>
> But we run into the problem that (^)/2 for floats is not the same as (^)/2 for rationals, we would need two different operators. When I posted this feature request, I might have had this idea. Meanwhile I have abandoned the above schema in favor of another schema.
>
> The new schema is based on different contexts and not on different datatypes, the advantage is that I don't need a (rdiv)/2 operator anymore:
>
> Context Approach:
> ============
> context division power
> float: (/)/2 (^)/2
> rational: (/)/2 (^)/2
>
> So I must appologize, since I issued a datatype feature request, whereby in the end I implemented myself a context feature, much later after I have issued this feature request here. I implemented the context feature via my new library(groebner/generic).
>
> The advantages of the context approach is as follows:
>
> Typing rdiv/2 is unnatural, its very clumsy, its much easier to type (/)/2.
> Programs can be easily moved from one context into anthor, we do not need to replace (/)/2 by (rdiv)/2.
> The context approach is also followed by CLP(Q), in CLP(Q) we do not need to write { X = Y rdiv Z } instead we write naturally { X = Y / Z }, right?
>
> Hope this helps!
>
> (*)
>
https://github.com/SWI-Prolog/swipl-devel/issues/185