01-13-2018, 12:22 AM
How would I produce repeating decimals such as 142857 being repeated endlessly for 1/7. Some CASIO calculators do so including the fax-115ES PLUS and the Japanese version of the CLASSWIZ fox-991EX.
(01-13-2018 12:22 AM)lrdheat Wrote: [ -> ]How would I produce repeating decimals such as 142857 being repeated endlessly for 1/7. Some CASIO calculators do so including the fax-115ES PLUS and the Japanese version of the CLASSWIZ fox-991EX.
LOCAL CRID:="REPEATING DECIMAL 0.01";
//Written 2018 StephenG1CMZ
//Following Joe Horn`s algorithm using Multiplicative Order
//Disclaimer: This implement yields visually useful results
// for some repeating decimals EG NN=208
//But stalls or slows given a non-repeating value.
//Large Repeating Lengths yield weird output eg NN=301
LOCAL FR2,FR5;
ZEROS(NN)
BEGIN
IF NN>0 THEN
RETURN "0"+ZEROS(NN-1);
END;
RETURN "";
END;
EXPORT MAXFACTOR25(NN)
BEGIN
LOCAL MAXFACTR:=0;
LOCAL LST,LP;
LST:=mat2list(ifactors(NN));
FR2:=0; FR5:=0;
LP:=POS(LST,2);
IF LP THEN
FR2:=LST(LP+1);
END;
LP:=POS(LST,5);
IF LP THEN
FR5:=LST(LP+1);
END;
MAXFACTR:=MAX(FR2,FR5);
RETURN MAXFACTR;//0=NONE
END;
EXPORT SOFAR (NN )
BEGIN
LOCAL TRANSIENTLEN:=MAXFACTOR25(NN);
LOCAL WHATSLEFT,MO;
LOCAL TP,RP,NDIGITS;
LOCAL ST;//STRINGVERSION
WHATSLEFT:=exact(NN/(2^FR2*5^FR5));
IF WHATSLEFT==1 THEN
MSGBOX("WHATS LEFT "+WHATSLEFT);
//RETURN 1/NN;//OR AVOID
END;
//PRINT("BEFORE");
//See http://www.hpmuseum.org/forum/thread-3212.html
MO:=MultiplicativeOrder(WHATSLEFT,10);
//PRINT("AFTER");
NDIGITS:=TRANSIENTLEN+MO;
//GET TP (WITHOUT ROUNDING LAST DIGIT)
TP:=(1/NN)*10^TRANSIENTLEN;
TP:=IP(TP)/(10^TRANSIENTLEN);
RP:=iquo(1*10^NDIGITS,NN);
//The string version asks for leading zeros I hoped
//but no...pad it manually
//ST:=format(RP,"s"+NDIGITS);
ST:=ZEROS(NDIGITS-DIM(STRING(RP)))+RP;
PRINT();
PRINT("Input Fraction: 1/"+NN);
PRINT("Whats Left: "+WHATSLEFT);
PRINT("Multiplicative Order: "+MO);
PRINT("Length: "+{TRANSIENTLEN,MO});
IF MO>12 THEN //EXPECT REPEATING PART TO GO WEIRD
PRINT("MO>12: CAUTION");
END;
PRINT("PPL REAL: "+1/NN);
PRINT("TRANSIENT PART: "+IFTE(TRANSIENTLEN,TP," (none)"));
PRINT(ST);
//NB REMEMBER THE LAST REPEATING DIGIT MUST NOT BE ROUNDED
//RETURN RESULTS
//TRANSIENTLEN=0 =NO TRANSIENT
//MO=0 =NO REPEATING
RETURN {{TRANSIENTLEN,TP},{MO,ST}};
END;
EXPORT NUMB()
BEGIN
PRINT(CRID);
//PRINT(SOFAR(208));
END;
(01-21-2018 10:22 PM)StephenG1CMZ Wrote: [ -> ]Jo Horn, it occurs to me that there is an important difference between your latest algorithm and the earlier one using Multiplicative Order, that might mean the earlier algorithm remains useful.
If I understand your latest algorithm correctly, it outputs the transient part and then keeps producing the recurring part until it identifies that it is going to repeat.
That means there is no advance knowledge of how long the repeating part is... Which could mean you consume lots of resources (time, disk space, ...) Producing lots of digits before exhausting resources.
By contrast, your solution using multiplicative order starts by working out how many recurring digits there will be...providing the opportunity to just return NaN before exhausting resources.
(01-21-2018 10:58 PM)StephenG1CMZ Wrote: [ -> ]I generate the repeating digits using a call to iquot (a built-in).
Quote:But in PPL it only works correctly up to 12 digits.
(01-23-2018 01:46 AM)tgray Wrote: [ -> ]Cool post. I learned something. I also implemented Joe's method for the DM42/Free42: link
I did notice that Joe's algorithm misses the first repeating period of 11632/864.
Quote:I think this is because when you factor 864 for factors of 2 and 5, you get 2^5 for the 2's.
Quote:So following the method, there are 5 non repeating digits after the decimal, even though there are actually only 2, with the next 3 being the first period of the repeating set of 3 digits. I didn't attempt to fix this.
11632/864 -> 13.46_296...