Version 0.5 is a much improved PPL program for showing transient parts and repetends of reciprocals. It has been rewritten to use CAS, enabling Transients and Repetends >12 digits to be handled, and is faster.
Code:
LOCAL CRID:="REPEATING DECIMAL V 0.5 \n©2018 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 ppl implement yields useful results using CAS
//to provide Transients and Repetends>12 digits
//Interesting Test Values:
//0,1,2,3,4,7,14,208,301,8192,8912
//8192 FIX TBD
LOCAL FR2,FR5;//GLOBAL RETURN
LOCAL WHATSLEFT,NDIGITS;//GLOBAL RETURN
EXPORT TransientLEN;//Length of Transient
EXPORT RepetendLEN;//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:=0;
LOCAL DIVBY0:="(NaN)(DIVBY0)";
MultiplicativeOrder10();//FORWARD
EXPORT ABOUT()
BEGIN
PRINT();
PRINT(CRID);
PRINT(ALGM);
END;
EXPORT HELP()
BEGIN
PRINT();
PRINT("GetLEN: Sets LENgth variables");
PRINT("Recurring/Repeating: Given integer NN, return a string of its real reciprocal with _ marking any recurring digits.");
PRINT("ShowReciprocal: Show Reciprocal");
PRINT("ShowReciprocals: Shows a range of reciprocal values.");
PRINT("Variables In: Strings DECSEP,USCORE ");
PRINT("Variables Out: RepetendLEN, TransientLEN");
PRINT("CAS: temporary variable");
END;
ZEROS(NN)
//Recursive is faster than using CAS
//and can output more zeros than PPL
BEGIN
//MSGBOX(NN);
IF NN>0 THEN
RETURN "0"+ZEROS(NN-1);
END;
RETURN "";
END;
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 GetLEN(NN)
BEGIN
TransientLEN:=MaxFactor25(NN);
WHATSLEFT:=exact(NN/(2^FR2*5^FR5));
RepetendLEN:=MultiplicativeOrder10(WHATSLEFT);
NDIGITS:=TransientLEN+RepetendLEN;
//PRINT({TransientLEN,RepetendLEN});
//DO NOT INCLUDE IP LENGTH
RETURN {TransientLEN,RepetendLEN,NDIGITS};
END;
ReDIGITS (NN)
//NN INTEGER
BEGIN
LOCAL LST;//UNUSED
LOCAL ST:="";//STRINGVERSION
LOCAL STR:="";
LOCAL TRANSIENTPART,REPETEND,INTPART;
LOCAL RESULTS;
LOCAL DP;//DECIMAL PLACES
LST:=GetLEN(NN);
//GetDecimalPlaces
//RP:=iquo((1*10^NDIGITS),NN);//works for repetends≤12digits:so use CAS
CAS("temporary:=iquo((1*10^NDIGITS),NN)");
ST:=CAS("string(temporary)");
STR:=ZEROS(NDIGITS-DIM(ST));
DP:=STR+ST;
//GetRepetend
REPETEND:=IFTE(RepetendLEN,MID(DP,TransientLEN+1),"");
//GetTransientDecimalPlaces
TRANSIENTPART:=IFTE(TransientLEN,LEFT(DP,TransientLEN),"");
//Get IntegerPart
INTPART:=IFTE(NN,(IP(1/NN)+DECSEP),DIVBY0);
RESULTS:=INTPART+TRANSIENTPART+USCORE+REPETEND;
//PRINT("RESULTS: "+RESULTS);
//Return a formatted string
//(Relevant Lengths are returned globally in ...LEN variables)
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;
GetTransient(NN)
//NB Only when USCORE NOT EMPTY
BEGIN
LOCAL ST:=ReDIGITS(NN);
RETURN LEFT(ST,INSTRING(ST,USCORE));
END;
EXPORT ShowReciprocal(NN)
BEGIN
LOCAL PXP:={0};
LOCAL TRANSIENTPART;
RECT_P();
TEXTOUT_P(CRID,0,0,3);
//TEXTOUT_P(ALGM,0,15,1);
TEXTOUT_P("Fraction,Reduced Fraction,Real,Decimal:",0,40);
TEXTOUT_P("1/"+NN,0,60);
TEXTOUT_P(CAS(1/NN)+" Reduced Fraction",0,80);
TEXTOUT_P(IFTE(NN,(1/NN),(DIVBY0))+" Real",0,100);
TRANSIENTPART:=GetTransient(NN);
PXP(0):=TEXTOUT_P(TRANSIENTPART+" Transient Part",0,140);
PXP(0):=TEXTOUT_P(Recurring(NN)+" Decimal",0,120);
TEXTOUT_P("Has "+TransientLEN+" Transient digits & "+RepetendLEN+" Repetend digits",0,180);
IF MAX(PXP)≥320 THEN //OFFSCREEN
TEXTOUT_P("PRINT(Recurring(NN)) may show more digits",0,200,3,RGB(255,0,0));
END;
TEXTOUT_P("Esc to continue",0,220);
WAIT;
END;
EXPORT ShowReciprocals(FIRST,LAST)
BEGIN
LOCAL NN;
FOR NN FROM FIRST TO LAST DO
ShowReciprocal(NN);
END;
END;
EXPORT MultiplicativeOrder10(WhatsLeft)
//See http://www.hpmuseum.org/forum/thread-3212.html
// WHATSLEFT
BEGIN
LOCAL AP:=0;
LOCAL NOTFND:=1;
LOCAL LST:={};//POSSIBLES TO CHECK
IF WhatsLeft≠1 THEN
//Get possibles
LST:=mat2list(idivis(euler(WhatsLeft)));
//Search possiblesfor a match
WHILE AP<SIZE(LST) AND NOTFND DO
AP:=AP+1;
IF powmod(10,LST(AP),WhatsLeft)==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));
END;
TESTS(TESTN)
//Perform some tests
BEGIN
LOCAL III,RR;
FOR III FROM 1 TO TESTN DO
//RECT_P();
//TEXTOUT_P(III,0,120);
DRAWMENU(III);
//WAIT(2);
TESTED:=III;
RR:=ReDIGITS(III);
END;
END;
EXPORT REDECIMALS()
BEGIN
LOCAL TESTN:=1000;
ABOUT();
PRINT(TESTN+" reciprocals in "+TEVAL(TESTS(TESTN)));
//HELP();
//PRINT(Recurring(8912));
END;
There are no specific limits other than unchecked list size/CAS integer limits.
In Show, a warning is given if screen size is exceeded, but such values can still be printed.