That's an interesting challenge Joe.
I've attempted to turn your algorithm using multiplicative order into what you could think of as pseudocode for a CAS solution...
I am more familiar with PPL than CAS, so this first attempt is in PPL.
As such, the range of inputs it works with is quite limited.
For example NN=208 (representing 1/208) works, but 301 doesn't.
And if whats left is 1, I think the call to MultiplicativeOrder either stalls or is slow.
Here is what I have so far
Code:
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;
But Joe has moved the goalposts and given us a new approach that no longer requires MultiplicativeOrder, so there is probably no further use for this implement.
Update: The maxfactors25 procedure here has a bug: Instead of seeing {3,2} as 3^2, it finds the 2 and sees that as 2^???. There is an updated version in the software library.