Version 0.3 includes an optimised MultiplicativeOrder (base 10) and outputs a string with the recurring part annotated with an underscore (selectable).
Code:
LOCAL CRID:="REPEATING DECIMAL (PPL) V 0.3 \nCode: StephenG1CMZ";
LOCAL ALGM:="Following Joe Horn's algorithm: http://www.hpmuseum.org/forum/thread-9919.html";
//Written 2018 StephenG1CMZ
//Following Joe Horn`s algorithm using Multiplicative Order
//This implement yields useful results but
//Large Repeating Lengths (>12repeatingdigits) yield weird output eg NN=301
//NB Sometimes the leading 0. is included in the output
//but sometimes it is not...EG NN=14 Why?
LOCAL ImpRELEN:=12;//(EMPIRICAL 12-15) 16 IS WRONG
LOCAL FR2,FR5;//GLOBAL RETURN
EXPORT TRANSIENTLEN;//Length of Transient
EXPORT RELEN;//Length of Recurring Digits/Repeating Digits
//^Len == Decimal Digits Only
EXPORT USCORE:="_";//CHANGE TO EMPTY STRING IF YOU WISH TO EVAL THE STRING
EXPORT DECSEP:=".";//DECIMAL SEPARATOR (USED WHEN TRANSIENTLEN=0,IDEALLY GET FROM SYSTEM)
EXPORT TESTED:={};
EXPORT ABOUT()
BEGIN
PRINT();
PRINT(CRID);
PRINT(ALGM);
END;
ZEROS(NN)
BEGIN
IF NN>0 THEN
RETURN "0"+ZEROS(NN-1);
END;
RETURN "";
END;
EXPORT MaxFactor25(NN)
BEGIN
LOCAL MAXFACTR:=0;
LOCAL LST,LSTB,LP,II;
LST:=mat2list(ifactors(NN)); //BASES AND COUNTSETC
//EXTRACT BASES (2,5) ETC
LSTB:=IFTE(SIZE(LST),MAKELIST(LST(2*II-1),II,1,(SIZE(LST)/2)),{});//{} HANDLES NN=1
FR2:=0; FR5:=0;
LP:=POS(LSTB,2);
IF LP THEN
FR2:=LST(2*LP);//EXPONENT
END;
LP:=POS(LSTB,5);
IF LP THEN
FR5:=LST(2*LP);//EXPONENT
END;
MAXFACTR:=MAX(FR2,FR5);
RETURN MAXFACTR;//0=NONE
END;
EXPORT MultiplicativeOrder10(WL)
//WL: WHATSLEFT
BEGIN
LOCAL AP:=0;
LOCAL NOTFND:=1;
LOCAL LST:={};//POSSIBLES TO CHECK
IF WL≠1 THEN
//Get possibles
LST:=mat2list(idivis(euler(WL)));
//Search possiblesfor a match
WHILE AP<SIZE(LST) AND NOTFND DO
AP:=AP+1;
IF powmod(10,LST(AP),WL)==1 THEN
NOTFND:=0;//FOUND
END;//IF
END;//LOOP
END;//IF
//Return match
//Return 0 if WL=1 or no match
RETURN IFTE(NOTFND,0,LST(AP));//TBC
END;
EXPORT GetTransient(NN)
BEGIN
LOCAL TRANSIENTPART;
TRANSIENTLEN:=MaxFactor25(NN);
IF TRANSIENTLEN THEN
TRANSIENTPART:=TRUNCATE((1/NN),TRANSIENTLEN);
ELSE
//DIVBY0 TBD
TRANSIENTPART:=IP(1/NN)+DECSEP;
END;
RETURN TRANSIENTPART;
END;
EXPORT ReDIGITS (NN )
//NN INTEGER
BEGIN
LOCAL TRANSIENTPART;
LOCAL WHATSLEFT;
LOCAL RP,NDIGITS;
LOCAL ST:="";//STRINGVERSION
LOCAL RESULTS:={};
LOCAL RL;
IF NN THEN
RL:=1/NN;//DIAGNOSTIC ONLY:USUAL REAL
ELSE
RETURN {"DIVBY0"};
END;
TRANSIENTPART:=GetTransient(NN);
WHATSLEFT:=exact(NN/(2^FR2*5^FR5));
IF WHATSLEFT==1 THEN
RETURN TRANSIENTPART;//AVOID STALL
END;
//See http://www.hpmuseum.org/forum/thread-3212.html
//RELEN:=MultiplicativeOrder(WHATSLEFT,10);
RELEN:=MultiplicativeOrder10(WHATSLEFT);
NDIGITS:=TRANSIENTLEN+RELEN;
IF RELEN>ImpRELEN THEN
//TBD: A better test might be to search for ᴇ in the string
ST:="(NaN)";//Implementation limit:BAD IQUO?
END;//FOR NOW SHOW THE WEIRD OUTPUT
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:=ST+MID(ZEROS(NDIGITS-DIM(STRING(RP)))+RP,TRANSIENTLEN+1);
RESULTS:=TRANSIENTPART+USCORE+ST;
//RESULTS:={{TRANSIENTLEN,TRANSIENTPART},{RELEN,ST},RL};//
IF 0 THEN //DEBUG INFO
PRINT();
PRINT("Input Fraction: 1/"+NN+" = "+RL);
PRINT("Whats Left: "+WHATSLEFT);
PRINT("Multiplicative Order: "+RELEN);
//PRINT("Length: "+{TRANSIENTLEN,RELEN});
IF RELEN>12 THEN //EXPECT REPEATING PART TO GO WEIRD
PRINT("RELEN>12: CAUTION");
END;
PRINT("TRANSIENT PART: "+IFTE(TRANSIENTLEN,TRANSIENTPART,TRANSIENTPART+" (none)"));
PRINT(ST);
PRINT(RESULTS);
END;
//RETURN RESULTS
//Return a formatted string
//(Relevant Lengths are returned globally)
RETURN RESULTS;
END;
EXPORT Recurring(NN)
BEGIN
RETURN ReDIGITS(NN);
END;
//Some call them Recurring
//Some call them Repeating
EXPORT Repeating(NN)
BEGIN
RETURN ReDIGITS(NN);
END;
EXPORT TESTS()
BEGIN
LOCAL III,RR;
FOR III FROM 1 TO 1000 DO
//RECT_P();
//TEXTOUT_P(III,0,120);
//WAIT(2);
TESTED(0):=III;
RR:=ReDIGITS(III);
END;
END;
EXPORT SHOWME()
BEGIN
LOCAL II;
FOR II FROM 1 TO 1000 DO
RECT_P();
TEXTOUT_P(II,0,20);
TEXTOUT_P(ReDIGITS(II),0,40);
WAIT;
END;
END;
EXPORT REDECIMALS()
BEGIN
ABOUT;
//PRINT((ReDIGITS(301)));
//WAIT;
//RECT_P();
PRINT(TEVAL(TESTS));
END;
Note there is a bug with the string formatting...Sometimes it includes the integer part, sometimes not.