Repeating Decimals / Recurring Decimals
01-21-2018, 11:00 AM (This post was last modified: 01-21-2018 04:34 PM by StephenG1CMZ.)
Post: #1
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
Repeating Decimals / Recurring Decimals
Given an integer reciprocal, analyzes the decimal representation to identify the transient and repeating/recurring parts of the decimal.

Eg
1/3 has no transient and 3 repeats.
1/4 has transient 0.25 and no repetition.
1/7 has no transient and 0.142857 recurring.
1/14 has transient 0 and 6 recurring digits.

For a description of the algorithms and more examples.

Stephen Lewkowicz (G1CMZ)
01-21-2018, 11:01 AM (This post was last modified: 01-21-2018 11:34 PM by StephenG1CMZ.)
Post: #2
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
RE: Repeating Decimals
(PPL) Version 0.2 follows the sequence of steps in Joe Horn's algorithm using MultiplicateOrder, which can be found here: http://www.hpmuseum.org/forum/thread-3212.html

Output is currently a list:
1: {Length of transient, transient}
2: {Length of recurring part, both parts but omitting the 0. Or 1.}
3: Just as a check, the real value.
The formatting could be improved.

Note that if the length of the recurring part exceeds 12 the recurring part returned is unreliable and should probably be replaced by NaN (the indicated length is OK, but not the digits...and sometimes they are not digits).

Code:
  LOCAL CRID:="REPEATING DECIMAL (PPL) V 0.2";  //Written 2018 StephenG1CMZ  //Following Joe Horns algorithm using Multiplicative Order  //This implement yields some useful results but  //Large Repeating Lengths (>12repeatingdigits) yield weird output eg NN=301  //The output format could be improved.  LOCAL ImpRELEN:=12;//EMPIRICAL  LOCAL FR2,FR5;  EXPORT TESTED:={};  ZEROS(NN)  BEGIN   IF NN>0 THEN    RETURN "0"+ZEROS(NN-1);   END;   RETURN "";   END;  TRUNCRR(NN,DIGITS)  //TRUNCATE A REAL RECIPROCAL  //NN:DENOMINATOR  //DIGITS:NUMBER OF PLACES TO KEEP  BEGIN   LOCAL TP;   TP:=(1/NN)*10^DIGITS;   TP:=IP(TP)/(10^DIGITS);   RETURN TP;  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 GETTRANSIENT(NN)  BEGIN   LOCAL TRANSIENTLEN,TRANSIENTPART;   TRANSIENTLEN:=MAXFACTOR25(NN);   TRANSIENTPART:=TRUNCRR(NN,TRANSIENTLEN);     RETURN {TRANSIENTLEN,TRANSIENTPART};  END;  EXPORT ReDIGITS (NN )  //NN INTEGER   BEGIN   LOCAL TRANSIENT; //TRANSIENTLEN,TRANSIENTPART;   LOCAL WHATSLEFT,MO;   LOCAL RP,NDIGITS;   LOCAL ST;//STRINGVERSION   LOCAL RESULTS:={};   LOCAL RL;   IF NN THEN    RL:=1/NN;//DIAGNOSTIC ONLY:USUAL REAL   ELSE    RETURN {"DIVBY0"};   END;   TRANSIENT:=GETTRANSIENT(NN);    WHATSLEFT:=exact(NN/(2^FR2*5^FR5));   IF WHATSLEFT==1 THEN    //AVOID STALL    RETURN {TRANSIENT,{0,0},RL};//AVOID STALL   END;   //PRINT("BEFORE");   //See http://www.hpmuseum.org/forum/thread-3212.html   MO:=MultiplicativeOrder(WHATSLEFT,10);   //PRINT("AFTER");   NDIGITS:=TRANSIENT(1)+MO;//TRANSIENTLEN   IF MO>ImpRELEN THEN    RP:="(NaN)";   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:=ZEROS(NDIGITS-DIM(STRING(RP)))+RP;   RESULTS:={TRANSIENT,{MO,ST},RL};//     IF 0 THEN //DEBUG INFO    PRINT();     PRINT("Input Fraction: 1/"+NN+" = "+RL);    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("TRANSIENT PART: "+IFTE(TRANSIENT(1),TRANSIENT(2),TRANSIENT(2)+" (none)"));    PRINT(ST);    PRINT(RESULTS);   END;      //RETURN RESULTS   //TRANSIENTLEN=0 =NO TRANSIENT   //MO=0 =NO REPEATING   //MO>Imp: IGNORE REPEATING DIGITS   //RL:REAL JUST FOR COMPARISON   RETURN RESULTS;  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 REDECIMALS()  BEGIN   PRINT(CRID);     //RECT_P();   PRINT(TEVAL(TESTS));  END;

Note: A comparable CAS implementation could improve ranges handled.

Update: 99989 crashes the Android emulator.

Stephen Lewkowicz (G1CMZ)
01-24-2018, 07:21 PM
Post: #3
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
RE: Repeating Decimals / Recurring Decimals
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 Horns 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.

Stephen Lewkowicz (G1CMZ)
01-26-2018, 11:02 PM (This post was last modified: 01-27-2018 07:27 PM by StephenG1CMZ.)
Post: #4
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
RE: Repeating Decimals / Recurring Decimals
Version 0.4 has cosmetic improvements and help. It adds a CAS variable which show more digits, but I have yet to find out how use that in PPL - Whenever I try to turn it into a string, it turns into a real instead.
(Update: I have found the required syntax to do that now, so expect another release soon.)

Code:
  LOCAL CRID:="REPEATING DECIMAL V 0.4 \n©2018 StephenG1CMZ";  LOCAL ALGM:="Following Joe Horn's algorithm: http://www.hpmuseum.org/forum/thread-9919.html";  //Written 2018 StephenG1CMZ  //Following Joe Horns 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)  LOCAL ImpTransientLEN:=12;//(EMPIRICAL)  //Should NDIGITS>12 fail?: not tested.  LOCAL FR2,FR5;//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 STNAN:="(NaN)";  MultiplicativeOrder10();//FORWARD  EXPORT ABOUT()  BEGIN   PRINT();   PRINT(CRID);   PRINT(ALGM);  END;  EXPORT HELP()  BEGIN   PRINT();   PRINT("Recurring/Repeating: Given integer NN, return a string of its real reciprocal with _ marking any recurring digits.");   PRINT("ShowMe: Shows a range of values.");   PRINT(" ");   PRINT("Variables In: Strings DECSEP,USCORE ");   PRINT("Variables Out: RepetendLEN, TransientLEN");   PRINT("CAS: temporary variable shows more digits: Can this be used from PPL?");   PRINT("{Repetend,Transient}>12 digits: NaN implemented (PPL Limit).");  END;  ZEROS(NN)  BEGIN   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 GetTransient(NN)  //NOTE: THIS IS CALLED BY Recurring/Repeating.  BEGIN   LOCAL TRANSIENTPART;   TransientLEN:=MaxFactor25(NN);   IF TransientLEN THEN    IF TransientLEN>12 THEN     //EG NN=8192     //MSGBOX("Caution:TransientLEN= "+TransientLEN);//FIX TBC     TRANSIENTPART:="(NaN)";//IP(1/NN);//AVOID TRUNCATE    ELSE     TRANSIENTPART:=TRUNCATE((1/NN),TransientLEN);//TRUNCATE BREAKS AT 13    END;   ELSE    IF NN==0 THEN     RETURN STNAN+"DIVBY0";    END;    TRANSIENTPART:=IP(1/NN)+DECSEP;   END;   RETURN TRANSIENTPART;  END;    ReDIGITS (NN )  //NN INTEGER   BEGIN   LOCAL STR:="";   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 STNAN+"DIVBY0";   END;   TRANSIENTPART:=GetTransient(NN);    WHATSLEFT:=exact(NN/(2^FR2*5^FR5));   IF WHATSLEFT==1 THEN    //RETURN TRANSIENTPART;//AVOID STALL   END;   //RepetendLEN:=MultiplicativeOrder(WHATSLEFT,10);   RepetendLEN:=MultiplicativeOrder10(WHATSLEFT);   NDIGITS:=TransientLEN+RepetendLEN;   IF RepetendLEN THEN    IF RepetendLEN>ImpRELEN THEN     //TBD: A better test might be to search for ᴇ in the string     ST:=STNAN;//Implementation limit:BAD IQUO?    END;//FOR NOW SHOW THE WEIRD OUTPUT    //MSGBOX({NDIGITS,NN});    RP:=iquo((1*10^NDIGITS),NN);   //MSGBOX(RP);    CAS("temporary:=iquo((1*10^NDIGITS),NN)");    //CAS("PRINT(temporary)");    //PRINT(STR);    //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(temporary)))+temporary,TransientLEN+1);   END;   RESULTS:=TRANSIENTPART+USCORE+ST;     IF 0 THEN //DEBUG INFO    PRINT();     PRINT("Input Fraction: 1/"+NN+" = "+RL);    PRINT("Whats Left: "+WHATSLEFT);    PRINT("Multiplicative Order: "+RepetendLEN);    //PRINT("Length: "+{TransientLEN,RepetendLEN});    IF RepetendLEN>12 THEN //EXPECT REPEATING PART TO GO WEIRD     PRINT("RepetendLEN>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 Show1(NN)  BEGIN     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)+" Real",(STNAN+"DIVBY0")),0,100);     //DEBUG;     TRANSIENTPART:=GetTransient(NN);     TEXTOUT_P(TRANSIENTPART+" Transient Part",0,140);     TEXTOUT_P(Recurring(NN)+" Decimal",0,120);     TEXTOUT_P("Has "+TransientLEN+" Transient digits & "+RepetendLEN+" Repetend digits",0,180);     TEXTOUT_P("Variable CAS.temporary may show more",0,200);     //TEXTOUT_P(CAS("temporary"),0,180);//doesnt work:PPL     TEXTOUT_P("Esc to continue",0,220);     IF RepetendLEN>ImpRELEN OR TransientLEN>ImpTransientLEN THEN      //Highlight Implement NaN      TEXTOUT_P("Imp"+STNAN,320/2,220,3,RGB(255,0,0));     END;     WAIT;   END;  EXPORT ShowMe(FIRST,LAST)  BEGIN   LOCAL NN;   FOR NN FROM FIRST TO LAST DO     Show1(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()  BEGIN   LOCAL III,RR;   FOR III FROM 1 TO 1000  DO    //RECT_P();    //TEXTOUT_P(III,0,120);     //WAIT(2);    TESTED:=III;    RR:=ReDIGITS(III);     END;  END;  EXPORT REDECIMALS()  BEGIN   ABOUT();    PRINT(TEVAL(TESTS));  END;
The implementation returns NaN if either the Transient part or Repetend exceed 12 digits.

Stephen Lewkowicz (G1CMZ)
01-31-2018, 09:10 AM
Post: #5
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
RE: Repeating Decimals / Recurring Decimals
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 Horns 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.

Stephen Lewkowicz (G1CMZ)
02-01-2018, 05:53 PM (This post was last modified: 02-01-2018 07:14 PM by StephenG1CMZ.)
Post: #6
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
RE: Repeating Decimals / Recurring Decimals
Version 0.6
Show optimised. Note that the transient display assumes USCORE (underscore) is not empty.
Implementation Limits added (Some large values eg NN=1E14 exceed the limits of euler).

Code:
  LOCAL CRID:="REPEATING DECIMAL V 0.6 \n©2018 StephenG1CMZ";  LOCAL ALGM:="Following Joe Horn's algorithm: http://www.hpmuseum.org/forum/thread-9919.html";  //Written 2018 StephenG1CMZ  //Following Joe Horns 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    LOCAL FR2,FR5;//GLOBAL RETURN  LOCAL WHATSLEFT,NDIGITS;//GLOBAL RETURN  LOCAL ImpLimST:="MultiplicativeOrder10: Implementation Limit!\n";  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;  EXPORT BigT:=0;  EXPORT BigR:=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("Hint:To PRINT long strings,");   PRINT("PRINT(a few bytes at a time)");  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      //Get Length   //A possible optimisation:   //Avoid recalc    LST:=GetLEN(NN);     //TBD:IF EXCESSIVE LENGTH RETURN NAN   //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  //NB RECALCULATES  BEGIN   LOCAL ST:=ReDIGITS(NN);   RETURN LEFT(ST,INSTRING(ST,USCORE));  END;  GetTransientToo(NN,ST)  //Requires ST to supply digits an4 USCORE  BEGIN   RETURN LEFT(ST,INSTRING(ST,USCORE));   END;  EXPORT ShowReciprocal(NN)  BEGIN     LOCAL PXP:={0};     LOCAL TRANSIENTPART;     LOCAL DST;     RECT_P();     TEXTOUT_P(CRID,0,0,3);     //TEXTOUT_P(ALGM,0,15,1);    TEXTOUT_P("Fraction,Reduced Fraction,Real,Decimal:",0,40);        // COMMON REPRESENTATIONS     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);     //EARLY LENGTH     //Note:This is recalculated in ReDIGITS     GetLEN(NN);     TEXTOUT_P("Has "+TransientLEN+" Transient digits & "+RepetendLEN+" Repetend digits",0,180);       //Main Display     DST:=Recurring(NN);     //TEXTOUT_P("Has "+TransientLEN+" Transient digits & "+RepetendLEN+" Repetend digits",0,180);//IF NOT EARLY        PXP(0):=TEXTOUT_P(DST+" Decimal",0,120);     TRANSIENTPART:=GetTransientToo(NN,DST);      PXP(0):=TEXTOUT_P(TRANSIENTPART+" Transient Part",0,140);         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)));    IF TYPE(LST)≠TYPE({}) THEN //EMPIRICAL TEST     //EG NN=1ᴇ14     MSGBOX(ImpLimST+LST);     RECT_P();//SAVE/RESTORE IDEALLY     //PERHAPS RETURN AND HANDLE NAN INSTEAD     //IF NOT CAUGHT powmod WILL FAIL    END;    IF TYPE(LST)==TYPE({}) THEN     //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   END;//VALID LST   //Return 0 if WL=1 or no match   RETURN IFTE(NOTFND,0,LST(AP));  END;  EXPORT TESTS(TESTN)  //Perform some tests  BEGIN   LOCAL III,RR;   FOR III FROM 1 TO TESTN DO    //RECT_P();    //TEXTOUT_P(III,0,120);    TESTED:=III;    RR:=ReDIGITS(III);    //Notethe biggest    IF TransientLEN>BigT THEN     BigT:=TransientLEN;    END;    IF RepetendLEN>BigR THEN     BigR:=RepetendLEN;    END;    DRAWMENU(III,BigT,BigR);//MAX    //DRAWMENU(III,TransientLEN,RepetendLEN);//CURRENT   END;  END;  EXPORT REDECIMALS()  BEGIN   LOCAL TESTN:=1000;   ABOUT();    //HEADLINE RATE: LARGER WILL BE SLOWER   PRINT(TESTN+" reciprocals in "+TEVAL(TESTS(TESTN)));   //PRINT(DIM(Recurring(29989)));   //HELP();   //PRINT(Recurring(8912));  END;

Hope this is useful, although it is only implemented for reciprocals.

Stephen Lewkowicz (G1CMZ)
02-04-2018, 06:46 PM (This post was last modified: 02-05-2018 10:11 PM by StephenG1CMZ.)
Post: #7
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
RE: Repeating Decimals / Recurring Decimals
Version 0.7 implements handling of fractions as well as reciprocals.

Code:
    LOCAL CRID:="REPEATING DECIMAL V 0.7 \n©2018 StephenG1CMZ";  LOCAL ALGM:="Following Joe Horn's algorithm: http://www.hpmuseum.org/forum/thread-9919.html";  //Written 2018 StephenG1CMZ  //Following Joe Horns 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    LOCAL FR2,FR5;//GLOBAL RETURN  LOCAL WHATSLEFT,NDIGITS;//GLOBAL RETURN  LOCAL ImpLimST:="MultiplicativeOrder10: Implementation Limit!\n";  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;  EXPORT BigT:=0;  EXPORT BigR:=0;  LOCAL DIVBY0:="(NaN)(DIVBY0)";  MultiplicativeOrder10();//FORWARD  EXPORT ABOUT()  BEGIN   PRINT();   PRINT(CRID);   PRINT(ALGM);  END;  EXPORT HELP()  BEGIN   PRINT();   PRINT(CRID);   PRINT(" Discovers characteristics of rational fractions that can be specified by an integer numerator and denominator.");   PRINT(" ");   PRINT("NB Fractions are input as 2 integers.\nDo not enter as Prime fractions.");   PRINT(" ");   PRINT("Scroll or Esc...");   PRINT(" ");   PRINT("API functions:");   PRINT(" ");   PRINT("GetLEN(fraction):");   PRINT("Returns lengths and Sets LENgth variables.\nLengths exclude the IP and non-digits.");   PRINT("GetLEN(1,3)={0,1}");   PRINT(" ");   PRINT("Recurring(fraction):");   PRINT("Repeating(fraction):");   PRINT("Returns a string of the real value with _ marking any recurring digits.");   PRINT("Recurring(1,3)=0._3");   PRINT(" ");   PRINT("MultiplicativeOrder10(WhatsLeft):");   PRINT("Implemented for base 10.");   PRINT(" ");   PRINT("Procedures:");   PRINT(" ");   PRINT("Show(fraction):");   PRINT("Show Representations on_screen");   PRINT("Show(1,3)");   PRINT(" ");   PRINT("ShowRange(Numer1,Numer2,Denom1,Denom2):");   PRINT("Show Range of fractions one by one\nShowRange(1,0,3,0) = Show(1,3)");   PRINT("ShowRange(1,2,3,4)=Show(1,3),Show(1,4),Show(2,3),Show(2,4)");   PRINT(" ");   PRINT("ShowReciprocals(Denom1,Denom2):");   PRINT("Shows a range of reciprocal values one by one.\nShowReciprocals(3,0)=Show(1,3)");   PRINT("ShowReciprocals(1,3)=Show(1,1),Show(1,2),Show(1,3)");   PRINT("");   PRINT("Variables In: Strings DECSEP,USCORE ");   PRINT("Variables Out: RepetendLEN, TransientLEN");   PRINT(" ");   PRINT("Hint: To PRINT long strings,");   PRINT("PRINT(a few bytes at a time)");  END;  //STANDARD ROUTINES    DIGITSNEEDED(NN)  //DIGITS NEEDED FOR IP  //EXCLUDES SIGN POINT SEPARATOR  BEGIN   IP(LOG(MAX(1,ABS(NN))))+1;  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;  //END STANDARD  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(NumerN,DenomN)  //Get TransientLEN,RepetendLEN,NDIGITS  //These lengths are decimal places and exclude IPLEN  //0 DENOMINATOR: RETURN {0,0,0}  BEGIN    LOCAL RedNUMER,RedDENOM;   IF DenomN THEN    //Step 0: Reduce Fraction    RedNUMER:=CAS("numer(NumerN/DenomN)");    RedDENOM:=CAS("denom(NumerN/DenomN)");    IF RedNUMER≠NumerN OR RedDENOM≠DenomN THEN     RETURN GetLEN(RedNUMER,RedDENOM);    END;    //Continue    TransientLEN:=MaxFactor25(DenomN);    WHATSLEFT:=exact(DenomN/(2^FR2*5^FR5));    RepetendLEN:=MultiplicativeOrder10(WHATSLEFT);    NDIGITS:=TransientLEN+RepetendLEN;     //PRINT({TransientLEN,RepetendLEN});   ELSE //DIVBY0    TransientLEN:=0;    RepetendLEN:=0;    NDIGITS:=0;   END;   RETURN {TransientLEN,RepetendLEN,NDIGITS};  END;  ReDIGITS (NUMER,NN)  //Determine Digits of the fraction (NUMER/NN)  //NUMERATOR INTEGER   //DENOMINATOR INTEGER  //DENOMINATOR 0 RETURNS NAN  BEGIN   LOCAL LST;//UNUSED   LOCAL ST:="";//STRINGVERSION   LOCAL STR:="";   LOCAL TRANSIENTPART,REPETEND,INTPART;   LOCAL RESULTS;   LOCAL DP;//DECIMAL PLACES   LOCAL IPLEN;   LOCAL RedNUMER,RedDENOM;   //Step 0: reduce fraction   RedNUMER:=CAS("numer(NUMER/NN)");   RedDENOM:=CAS("denom(NUMER/NN)");   IF RedNUMER≠NUMER OR RedDENOM≠NN THEN    RETURN ReDIGITS(RedNUMER,RedDENOM);   END;   //Continue...   //Get Length   //A possible optimisation:   //Avoid recalc    LST:=GetLEN(NUMER,NN);     //TBD:IF EXCESSIVE LENGTH RETURN NAN   //GetDecimalPlaces   //RP:=iquo((1*10^NDIGITS),NN);//works for repetends≤12digits:so use CAS     CAS("temporary:=iquo(((NUMER*10^NDIGITS),NN)");   ST:=CAS("string(temporary)");   //MSGBOX(ST);   STR:=ZEROS(NDIGITS-DIM(ST));   DP:=STR+ST;    INTPART:=IFTE(NN,(IP(NUMER/NN)+DECSEP),DIVBY0);    //IF NUMER==1 THEN    //RECIPROCAL:iquo returns decimal places only   IF NN AND NUMER≠1 THEN    //FRACTION: iquo returns IP and decimals with no point    IPLEN:=DIGITSNEEDED(IP(NUMER/NN));//LEN OF IP    //INTPART:=LEFT(DP,IPLEN)+DECSEP; //IP    DP:=MID(DP,IPLEN+1); //DP   END;   //GetRepetend   REPETEND:=IFTE(RepetendLEN,MID(DP,TransientLEN+1),"");   //GetTransientDecimalPlaces   TRANSIENTPART:=IFTE(TransientLEN,LEFT(DP,TransientLEN),"");   //Get IntegerPart     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(NumerN,DenomN)  BEGIN   RETURN ReDIGITS(NumerN,DenomN);   END;  //Some call them Recurring  //Some call them Repeating  EXPORT Repeating(NumerN,DenomN)  BEGIN   RETURN ReDIGITS(NumerN,DenomN);  END;  GetTransient(NUMER,NN)  //NB Only when USCORE NOT EMPTY  //NB RECALCULATES  BEGIN   LOCAL ST:=ReDIGITS(NUMER,NN);   RETURN LEFT(ST,INSTRING(ST,USCORE));  END;  GetTransientToo(NUMER,NN,ST)  //Requires ST to supply digits an4 USCORE  BEGIN   RETURN LEFT(ST,INSTRING(ST,USCORE));   END;  EXPORT Show(NumerN,DenomN)  BEGIN     LOCAL PXP:={0};     LOCAL TRANSIENTPART;     LOCAL DST;     LOCAL RedDENOM;     RECT_P();     TEXTOUT_P(CRID,0,0,3);     //TEXTOUT_P(ALGM,0,15,1);    TEXTOUT_P("Fraction,Reduced Fraction,Real,Decimal:",0,40);        // COMMON REPRESENTATIONS     TEXTOUT_P(NumerN+"/"+DenomN,0,60);     TEXTOUT_P(CAS(NumerN/DenomN)+" Reduced Fraction",0,80);     TEXTOUT_P(IFTE(DenomN,(NumerN/DenomN),(DIVBY0))+" Real",0,100);     //EARLY LENGTH     //Note:This is recalculated in ReDIGITS     GetLEN(NumerN,DenomN);     TEXTOUT_P("Has "+TransientLEN+" Transient digits & "+RepetendLEN+" Repetend digits",0,180);       //Main Display     DST:=Recurring(NumerN,DenomN);     //TEXTOUT_P("Has "+TransientLEN+" Transient digits & "+RepetendLEN+" Repetend digits",0,180);//IF NOT EARLY        PXP(0):=TEXTOUT_P(DST+" Decimal",0,120);     TRANSIENTPART:=GetTransientToo(NumerN,DenomN,DST);      PXP(0):=TEXTOUT_P(TRANSIENTPART+" Transient Part",0,140);         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 ShowRange(Numer1,Numer2,Denom1,Denom2)    BEGIN   LOCAL II,JJ;   FOR II FROM Numer1 TO MAX(Numer2,Numer1) DO    FOR JJ FROM Denom1  TO MAX(Denom2,Denom1) DO     Show(II,JJ);    END;   END;  END;  EXPORT ShowReciprocals(FIRST,LAST)  BEGIN   LOCAL NN;   FOR NN FROM FIRST TO MAX(LAST,FIRST) DO    Show(1,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)));    IF TYPE(LST)≠TYPE({}) THEN //EMPIRICAL TEST     //EG NN=1ᴇ14     MSGBOX(ImpLimST+LST);     RECT_P();//SAVE/RESTORE IDEALLY     //PERHAPS RETURN AND HANDLE NAN INSTEAD     //IF NOT CAUGHT powmod WILL FAIL    END;    IF TYPE(LST)==TYPE({}) THEN     //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   END;//VALID LST   //Return 0 if WL=1 or no match   RETURN IFTE(NOTFND,0,LST(AP));  END;  EXPORT TESTS(TESTN)  //Perform some tests  BEGIN   LOCAL III,RR;   FOR III FROM 1 TO TESTN DO    //RECT_P();    //TEXTOUT_P(III,0,120);    TESTED:=III;    RR:=ReDIGITS(2,III);    //Note the biggest    IF TransientLEN>BigT THEN     BigT:=TransientLEN;    END;    IF RepetendLEN>BigR THEN     BigR:=RepetendLEN;    END;    DRAWMENU(III,BigT,BigR);//MAX    //DRAWMENU(III,TransientLEN,RepetendLEN);//CURRENT   END;  END;  EXPORT REDECIMALS()  BEGIN   LOCAL TESTN:=1000;   ABOUT();    //HEADLINE RATE: LARGER WILL BE SLOWER   PRINT(TESTN+" fractions in "+TEVAL(TESTS(TESTN)));   //PRINT(DIM(Recurring(1,29989)));   //HELP();  END;

Update: use with care.
On the Android, this implementation can be problematic with larger values such as 2/16384.
Sometimes it seems to work and can return useful results, but after a Bad Argument error is reported, problems persist in the running of other programs until the calculator (not the mobile) is switched off.

Stephen Lewkowicz (G1CMZ)
02-06-2018, 11:24 PM (This post was last modified: 02-07-2018 07:47 PM by StephenG1CMZ.)
Post: #8
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
RE: Repeating Decimals / Recurring Decimals
I have noticed an issue with the step 0 fraction reduction as I have implemented it in V0.7.

In V0.6, 1/1E14 would be processed by the algorithm (no reduction being implemented).
An error message would issue from Multiplicateorder10 as implementation limits are exceeded.

In V0.7, 1/1E14 is reduced to 1E-14/1 and non-integer numerator is processed, resulting in a NaN with no error message from MultiplicativeOrder10 seen.

Potentially, there might be other values which MultiplicateOrder10 might have handled, but which are not being processed because the reduction step is introducing unexpected non-integer values.

Stephen Lewkowicz (G1CMZ)
02-07-2018, 08:02 PM
Post: #9
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
RE: Repeating Decimals / Recurring Decimals
Note that some long repetends incorrectly return all zeros instead of the correct digits (the reported length is correct). If you see a value with just zeros assume it is incorrect.

Stephen Lewkowicz (G1CMZ)
02-08-2018, 09:03 PM (This post was last modified: 02-08-2018 10:10 PM by StephenG1CMZ.)
Post: #10
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
RE: Repeating Decimals / Recurring Decimals
Version 0.8

Improved handling of implementation limitations.
Improved user interface shows more digits on-screen and allows long strings not to be generated.
Code:
     LOCAL CRID:="REPEATING DECIMAL V 0.8 \n©2018 StephenG1CMZ";  LOCAL ALGM:="Following Joe Horn's algorithm: http://www.hpmuseum.org/forum/thread-9919.html";  //Written 2018 StephenG1CMZ  //Following Joe Horns algorithm using Multiplicative Order  //This ppl implement yields useful results using CAS   //to provide Transients and Repetends>12  digits    LOCAL FR2,FR5;//GLOBAL RETURN  LOCAL WHATSLEFT,NDIGITS;//GLOBAL RETURN  LOCAL ImpPRINT:=2000;//PRINT LIMIT <2K  LOCAL ImpSTRING:=64000;//LIMIT VALUE TBC    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 WAITS:=0;  EXPORT ImpRELEN:=ImpSTRING;//MAX LEN TO GENERATE  EXPORT TESTED:=0;  EXPORT BigT:=0;  EXPORT BigR:=0; LOCAL STNAN:="(NaN)";  LOCAL DIVBY0:=STNAN+"{0}";//DIVBY0  LOCAL NOTINT:=STNAN+"(NotInteger)";  LOCAL STNANImp:=STNAN+"(Imp)";//Implemenation Limit  LOCAL ImpLimST:="MultiplicativeOrder10: Implementation Limit!\n";    MultiplicativeOrder10();//FORWARD  EXPORT ABOUT()  BEGIN   PRINT();   PRINT(CRID);   PRINT(ALGM);  END;  EXPORT HELP()  BEGIN   PRINT();   PRINT(CRID);   PRINT(" Discovers characteristics of rational fractions that can be specified by an integer numerator and denominator.");   PRINT(" ");   PRINT("NB Fractions are input as 2 integers.\nDo not enter as Prime fractions.");   PRINT(" ");   PRINT("Scroll or Esc...");   PRINT(" ");   PRINT("API functions:");   PRINT(" ");   PRINT("GetLEN(fraction):");   PRINT("Returns lengths and Sets LENgth variables.\nLengths exclude the IP and non-digits.");   PRINT("GetLEN(1,3)={0,1}");   PRINT(" ");   PRINT("Recurring(fraction):");   PRINT("Repeating(fraction):");   PRINT("Returns a string of the real value with _ marking any recurring digits.");   PRINT("Recurring(1,3)=0._3");   PRINT(" ");   PRINT("MultiplicativeOrder10(WhatsLeft):");   PRINT("Implemented for base 10.");   PRINT(" ");   PRINT("Procedures:");   PRINT(" ");   PRINT("Show(fraction):");   PRINT("Show Representations on_screen");   PRINT("[Esc] to continue to next page");   PRINT("[View] more digits");   PRINT("Show(1,3)");   PRINT(" ");   PRINT("ShowRange(Numer1,Numer2,Denom1,Denom2):");   PRINT("Show Range of fractions one by one\nShowRange(1,0,3,0) = Show(1,3)");   PRINT("ShowRange(1,2,3,4)=Show(1,3),Show(1,4),Show(2,3),Show(2,4)");   PRINT(" ");   PRINT("ShowReciprocals(Denom1,Denom2):");   PRINT("Shows a range of reciprocal values one by one.\nShowReciprocals(3,0)=Show(1,3)");   PRINT("ShowReciprocals(1,3)=Show(1,1),Show(1,2),Show(1,3)");   PRINT("");   PRINT("Variables In: (Selectable by user @Home)");   PRINT("ImpRELEN: Recurring LEN limit");//Limit to manageable length   PRINT("String USCORE: Underscore ");   PRINT("WAITS: Show WAIT time (0=Esc)");   PRINT(" ");   PRINT("Variables Out:");   PRINT("RepetendLEN, TransientLEN");   PRINT(" ");   PRINT("Known Limitations:");   PRINT("Numbers beyond about 1/12109:");   PRINT("Repetend digits incorrectly show just 0-s (LEN OK)");   PRINT(" ");   PRINT("Hint: To PRINT long strings,");   PRINT("PRINT(a few bytes at a time)");   PRINT(" ");   PRINT("Interesting Test Values:");   PRINT("{1/: 0,1,2,3,4,7,14,208,301,8192}");   PRINT("{1/: 29989}//WRONG}");   PRINT("{1/: 3^15}//CRASH AVOIDED");   PRINT("{2/: 16384}")  END;  //STANDARD ROUTINES  DecSepNow()  //RETURN current system decimal separator  //From the forum  BEGIN   RETURN IFTE((HSeparator MOD 9)<4,".",",");  END;  //QUERY:WOULD TAKING LOGS OF NUMERATOR AND DENOMINATOR AND SUBTRACTING  //IMPROVE RANGE OR PRECISION TBD  DIGITSNEEDED(NN)  //DIGITS NEEDED FOR IP  //EXCLUDES SIGN POINT SEPARATOR  BEGIN   IP(LOG(MAX(1,ABS(NN))))+1;  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;  //END STANDARD  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(NumerN,DenomN)  //Get TransientLEN,RepetendLEN,NDIGITS  //These lengths are decimal places and exclude IPLEN  //0 DENOMINATOR: RETURN {0,0,0}  BEGIN   LOCAL GD;    LOCAL RedNUMER,RedDENOM;   IF DenomN THEN    //Step 0: Reduce Fraction    GD:=gcd(NumerN,DenomN);    RedNUMER:=NumerN/GD;    RedDENOM:=DenomN/GD;       //Continue    TransientLEN:=MaxFactor25(RedDENOM);    WHATSLEFT:=exact(RedDENOM/(2^FR2*5^FR5));    RepetendLEN:=MultiplicativeOrder10(WHATSLEFT);    NDIGITS:=TransientLEN+RepetendLEN;     //PRINT({TransientLEN,RepetendLEN});   ELSE //DIVBY0    TransientLEN:=0;    RepetendLEN:=0;    NDIGITS:=0;   END;   RETURN {TransientLEN,RepetendLEN,NDIGITS};  END;  ReDIGITS (NUMER,NN)  //Determine Digits of the fraction (NUMER/NN)  //NUMERATOR INTEGER   //DENOMINATOR INTEGER  //NEGATIVES OK  //DENOMINATOR 0: RETURN NAN  //NONINTEGER: UNCHECKED  BEGIN   LOCAL GD;   LOCAL LST;//UNUSED   LOCAL ST:="";//STRINGVERSION   LOCAL STR:="";   LOCAL TRANSIENTPART,REPETEND,INTPART;   LOCAL RESULTS;   LOCAL DP;//DECIMAL PLACES   LOCAL IPLEN;   LOCAL RedNUMER,RedDENOM;   //MSGBOX({NUMER,NN});   //GUARDS   IF NN==0 THEN    RETURN DIVBY0;   END;   IF FP(NUMER) OR FP(NN) THEN    RETURN NOTINT+STRING({NUMER,NN});//PARAMETERS NOT INTEGER   END;   IF (NUMER/NN)<0 THEN    RETURN "−"+ReDIGITS(ABS(NUMER),ABS(NN));   END;   //OK   //Step 0: reduce fraction   GD:=gcd(NUMER,NN);   RedNUMER:=NUMER/GD;   RedDENOM:=NN/GD;     //Continue...   //Get Length   //A possible optimisation:   //Avoid recalc    LST:=GetLEN(RedNUMER,RedDENOM);   //IF EXCESSIVE LENGTH RETURN NAN   IF NDIGITS>MIN(ImpRELEN,ImpSTRING-9) THEN //−9-ALLOW FOR DECSEP ETC    //STRING:TOO LONG TO GENERATE    //RELEN:USER LIMIT(TOO LONG/SLOW FOR USER)    RETURN STNANImp;    END;   //GetDecimalPlaces   //RP:=iquo((1*10^NDIGITS),NN);//works for repetends≤12digits:so use CAS     CAS("temporary:=iquo(((RedNUMER*10^NDIGITS),RedDENOM)");   ST:=CAS("string(temporary)");   //MSGBOX(ST);   STR:=ZEROS(NDIGITS-DIM(ST));   DP:=STR+ST;    //GetINTEGERPART   INTPART:=IFTE(RedDENOM,(IP(RedNUMER/RedDENOM)+DecSepNow()),DIVBY0);//THIS DIVBY IS GUARDED   //IF NUMER==1 THEN    //RECIPROCAL:iquo returns decimal places only   IF RedNUMER≠1 THEN //NN    //FRACTION: iquo returns IP and decimals with no point    IPLEN:=DIGITSNEEDED(exact(RedNUMER/RedDENOM));//LEN OF IP    DP:=MID(DP,IPLEN+1); //DP   END;   //GetRepetend   REPETEND:=IFTE(RepetendLEN,MID(DP,TransientLEN+1),"");   //GetTransientDecimalPlaces   TRANSIENTPART:=IFTE(TransientLEN,LEFT(DP,TransientLEN),"");      RESULTS:=INTPART+TRANSIENTPART+USCORE+REPETEND;   //PRINT("RESULTS: "+RESULTS);   //Imp:Sometimes the string contains source   IF INSTRING(RESULTS,"M") THEN    RESULTS:=STNANImp+RESULTS;//MARK BAD RESULT    END;    //Return a formatted string   //(Relevant Lengths are returned globally in ...LEN variables)    RETURN RESULTS;    END;    EXPORT Recurring(NumerN,DenomN)  BEGIN   RETURN ReDIGITS(NumerN,DenomN);   END;  //Some call them Recurring  //Some call them Repeating  EXPORT Repeating(NumerN,DenomN)  BEGIN   RETURN ReDIGITS(NumerN,DenomN);  END;  GetTransient(NUMER,NN)  //NB Only when USCORE NOT EMPTY  //NB RECALCULATES  BEGIN   LOCAL ST:=ReDIGITS(NUMER,NN);   RETURN LEFT(ST,INSTRING(ST,USCORE));  END;  GetTransientToo(NUMER,NN,ST)  //Requires ST to supply digits an4 USCORE  BEGIN   RETURN LEFT(ST,INSTRING(ST,USCORE));   END;  EXPORT Show(NumerN,DenomN)  BEGIN     LOCAL PXP:={0};     LOCAL TRANSIENTPART;     LOCAL DST;     LOCAL RedDENOM;     LOCAL KK,LST;     RECT_P();     TEXTOUT_P(CRID,0,0,3);     //TEXTOUT_P(ALGM,0,15,1);    TEXTOUT_P("Fraction,Reduced Fraction,Real,Decimal:",0,40);        // COMMON REPRESENTATIONS     TEXTOUT_P(NumerN+"/"+DenomN,0,60);     TEXTOUT_P(CAS(NumerN/DenomN)+" Reduced Fraction",0,80);//NEEDS FIXING     TEXTOUT_P(IFTE(DenomN,(NumerN/DenomN),(DIVBY0))+" Real",0,100);     //EARLY LENGTH     //Note:This is recalculated in ReDIGITS     LST:=GetLEN(NumerN,DenomN);     TEXTOUT_P("Has "+TransientLEN+" Transient digits & "+RepetendLEN+" Repetend digits",0,180);       //Main Display     DST:=Recurring(NumerN,DenomN);     //TEXTOUT_P("Has "+TransientLEN+" Transient digits & "+RepetendLEN+" Repetend digits",0,180);//IF NOT EARLY        PXP(0):=TEXTOUT_P(DST+" Decimal",0,120);     TRANSIENTPART:=GetTransientToo(NumerN,DenomN,DST);      PXP(0):=TEXTOUT_P(TRANSIENTPART+" Transient Part",0,140);     IF INSTRING(DST,"00000000000000") THEN      //Loss Of significance suspected      TEXTOUT_P(" ! Check Possible Loss Of Significance !",0,200,3,RGB(255,0,0));     END;     IF MAX(PXP)≥320 THEN //OFFSCREEN      TEXTOUT_P("[View]",320*(4/6),220,3,RGB(255,0,0));     END;       TEXTOUT_P(IFTE(WAITS>0,"Wait...","[Esc]"),320*(5/6),220,3);       KK:=WAIT(WAITS);      IF KK==9 THEN //VIEW KEY      PRINT();      PRINT(NumerN+"/"+DenomN);      PRINT(LST);      PRINT(MID(DST,1,ImpPRINT));      IF DIM(DST)>ImpPRINT THEN       PRINT("PRINT Unable");//Or:Loop      END;      //WAIT(WAITS);     END;     RETURN DST;  END;  EXPORT ShowRange(Numer1,Numer2,Denom1,Denom2)  //Show range one by one  BEGIN   LOCAL II,JJ;   FOR II FROM Numer1 TO MAX(Numer2,Numer1) DO    FOR JJ FROM Denom1  TO MAX(Denom2,Denom1) DO     Show(II,JJ);    END;   END;  END;  EXPORT ShowReciprocals(FIRST,LAST)  BEGIN   LOCAL NN;   FOR NN FROM FIRST TO MAX(LAST,FIRST) DO    Show(1,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)));    IF TYPE(LST)≠TYPE({}) THEN //EMPIRICAL TEST     //EG NN=1ᴇ14     MSGBOX(ImpLimST+LST);     RECT_P();//SAVE/RESTORE IDEALLY     //PERHAPS RETURN AND HANDLE NAN INSTEAD     //IF NOT CAUGHT powmod WILL FAIL    END;    IF TYPE(LST)==TYPE({}) THEN     //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   END;//VALID LST   //Return 0 if WL=1 or no match   RETURN IFTE(NOTFND,0,LST(AP));  END;  EXPORT TESTS(TESTN)  //Perform some tests  BEGIN   LOCAL III,RR;   FOR III FROM 1 TO TESTN DO    //RECT_P();    //TEXTOUT_P(III,0,120);    TESTED:=III;    RR:=ReDIGITS(2,III);    //Note the biggest    IF TransientLEN>BigT THEN     BigT:=TransientLEN;    END;    IF RepetendLEN>BigR THEN     BigR:=RepetendLEN;    END;    DRAWMENU(III,BigT,BigR);//MAX    //DRAWMENU(III,TransientLEN,RepetendLEN);//CURRENT   END;  END;  EXPORT REDECIMALS()  BEGIN   LOCAL TESTN:=1000;   ABOUT();    //HEADLINE RATE: LARGER WILL BE SLOWER   PRINT(TESTN+" fractions in "+TEVAL(TESTS(TESTN)));   //PRINT(DIM(Recurring(1,29989)));   //HELP();  END;
Note that some long repetends incorrectly show all zeros. These will be highlighted in Show but do not raise a NaN.

Stephen Lewkowicz (G1CMZ)
02-10-2018, 11:15 PM (This post was last modified: 02-11-2018 11:38 PM by StephenG1CMZ.)
Post: #11
 StephenG1CMZ Senior Member Posts: 803 Joined: May 2015
RE: Repeating Decimals / Recurring Decimals
Version 0.9 fixes a bug caused by "exact", introduced in V0.8. Thanks for spotting that.
Error MSGBOX is improved (using an AFile to save/restore the screen).

Code:
     LOCAL CRID:="REPEATING DECIMAL V 0.9 \n©2018 StephenG1CMZ";  LOCAL ALGM:="Following Joe Horn's algorithm: http://www.hpmuseum.org/forum/thread-9919.html";  //Written 2018 StephenG1CMZ  //Following Joe Horns algorithm using Multiplicative Order  //This ppl implement yields useful results using CAS   //to provide Transients and Repetends>12  digits    LOCAL FR2,FR5;//GLOBAL RETURN  LOCAL WHATSLEFT,NDIGITS;//GLOBAL RETURN  LOCAL ImpPRINT:=2000;//PRINT LIMIT <2K  LOCAL ImpSTRING:=64000;//LIMIT VALUE TBC  EXPORT RedNUMER,RedDENOM;  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 WAITS:=0;  EXPORT ImpRELEN:=ImpSTRING;//MAX LEN TO GENERATE  EXPORT TESTED:=0;  EXPORT BigT:=0;  EXPORT BigR:=0;  LOCAL STNAN:="(NaN)";  LOCAL DIVBY0:=STNAN+"{0}";//DIVBY0  LOCAL NOTINT:=STNAN+"(NotInteger)";  LOCAL STNANImp:=STNAN+"(Imp)";//Implemenation Limit   LOCAL FL:="ZTmpMESSAGEBOX";  LOCAL ImpLimST:="MultiplicativeOrder10: Implementation Limit!\n";  MultiplicativeOrder10();//FORWARD  EXPORT ABOUT()  BEGIN   PRINT();   PRINT(CRID);   PRINT(ALGM);  END;  EXPORT HELP()  BEGIN   PRINT();   PRINT(CRID);   PRINT(" Discovers characteristics of rational fractions that can be specified by an integer numerator and denominator.");   PRINT(" ");   PRINT("NB Fractions are input as 2 integers.\nDo not enter as Prime fractions.");   PRINT(" ");   PRINT("Scroll or Esc...");   PRINT(" ");   PRINT("API functions:");   PRINT(" ");   PRINT("GetLEN(fraction):");   PRINT("Returns lengths and Sets LENgth variables.\nLengths exclude the IP and non-digits.");   PRINT("GetLEN(1,3)={0,1}");   PRINT(" ");   PRINT("Recurring(fraction):");   PRINT("Repeating(fraction):");   PRINT("Returns a string of the real value with _ marking any recurring digits.");   PRINT("Recurring(1,3)=0._3");   PRINT(" ");   PRINT("MultiplicativeOrder10(WhatsLeft):");   PRINT("Implemented for base 10.");   PRINT(" ");   PRINT("Procedures:");   PRINT(" ");   PRINT("Show(fraction):");   PRINT("Show Representations on_screen");   PRINT("Key [Esc] to continue to next page");   PRINT("Key [View] for more digits");   PRINT("(Do not tap)");   PRINT("Show(1,3)");   PRINT(" ");   PRINT("ShowRange(Numer1,Numer2,Denom1,Denom2):");   PRINT("Show Range of fractions one by one\nShowRange(1,0,3,0) = Show(1,3)");   PRINT("ShowRange(1,2,3,4)=Show(1,3),Show(1,4),Show(2,3),Show(2,4)");   PRINT(" ");   PRINT("ShowReciprocals(Denom1,Denom2):");   PRINT("Shows a range of reciprocal values one by one.\nShowReciprocals(3,0)=Show(1,3)");   PRINT("ShowReciprocals(1,3)=Show(1,1),Show(1,2),Show(1,3)");   PRINT("");   PRINT("Variables In: (Selectable by user @Home)");   PRINT("ImpRELEN: Recurring LEN limit");//Limit to manageable length   PRINT("String USCORE: Underscore ");   PRINT("WAITS: Show WAIT time (0=Esc)");   PRINT(" ");   PRINT("Variables Out:");   PRINT("RepetendLEN, TransientLEN//Lengths");   PRINT("RedNUMER, RedDENOM//Reduced");   PRINT("(set by GetLEN,Recurring,Repeating)");   PRINT(" ");   PRINT("Known Limitations:");   PRINT("Numbers beyond about 1/12109:");   PRINT("Repetend digits incorrectly show just 0-s (LEN OK)");   PRINT("Negative inputs may error.");   PRINT(" ");   PRINT("Hint: To PRINT long strings,");   PRINT("PRINT(a few bytes at a time)");   PRINT(" ");   PRINT("Interesting Test Values:");   PRINT("{1/: 0,1,2,3,4,7,14,208,301,8192}");   PRINT("{1/: 29989}//WRONG}");   PRINT("{1/: 1ᴇ14}//Imp");   PRINT("{1/: 3^15}//ImpCRASH AVOIDED");   PRINT("{2/: 3}");   PRINT("{2/: 16384}");   PRINT("{123/208}");  END;  //STANDARD ROUTINES  DecSepNow()  //RETURN current system decimal separator  //From the forum  BEGIN   RETURN IFTE((HSeparator MOD 9)<4,".",",");  END;  DIGITSNEEDED(NN)  //DIGITS NEEDED FOR IP  //EXCLUDES SIGN POINT SEPARATOR  BEGIN   //RETURN IP(LOG(MAX(1,ABS(NN))))+1;//PORTABLE   RETURN MAX(0,(XPON(NN)))+1;//PRIME XPON=BASE 10  END;  SCR_GET()  BEGIN   G0:=AFiles(FL)  END;  SCR_PUT()  BEGIN   AFiles(FL):=G0;  END;  ZMSGBOX(ST,OKC)  BEGIN     SCR_PUT();   OKC:=MSGBOX(ST,OKC);   SCR_GET();   RETURN OKC;  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;  //END STANDARD  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(NumerN,DenomN)  //Get TransientLEN,RepetendLEN,NDIGITS  //These lengths are decimal places and exclude IPLEN  //0 DENOMINATOR: RETURN {0,0,0}  //NEGATIVES:UNCHECKED  BEGIN   LOCAL GD;    IF DenomN THEN    //Step 0: Reduce Fraction    GD:=gcd(NumerN,DenomN);    RedNUMER:=NumerN/GD;    RedDENOM:=DenomN/GD;       //Continue    TransientLEN:=MaxFactor25(RedDENOM);    WHATSLEFT:=exact(RedDENOM/(2^FR2*5^FR5));    RepetendLEN:=MultiplicativeOrder10(WHATSLEFT);    NDIGITS:=TransientLEN+RepetendLEN;     //PRINT({TransientLEN,RepetendLEN});   ELSE //DIVBY0    TransientLEN:=0;    RepetendLEN:=0;    NDIGITS:=0;   END;   //NOTE: 0,0 IS OFTEN SUGGESTIVE OF AN ERROR   //BUT IS ALSO RETURNED BY 1/1   //SO MAYBE USE AN ERRORFLAG?   RETURN {TransientLEN,RepetendLEN,NDIGITS};  END;  ReDIGITS (NUMER,NN)  //Determine Digits of the fraction (NUMER/NN)  //NUMERATOR INTEGER   //DENOMINATOR INTEGER  //NEGATIVES:ATTEMPTED BUT RAISE ERROR  //DENOMINATOR 0: RETURN NAN  //NONINTEGER: RETURN NAN  BEGIN   LOCAL GD;   LOCAL LST;//UNUSED   LOCAL ST:="";//STRINGVERSION   LOCAL STR:="";   LOCAL TRANSIENTPART,REPETEND,INTPART;   LOCAL RESULTS;   LOCAL DP;//DECIMAL PLACES   LOCAL IPLEN;   //MSGBOX({NUMER,NN});   //GUARDS   IF NN==0 THEN    RETURN DIVBY0;   END;   IF FP(NUMER) OR FP(NN) THEN    RETURN NOTINT+STRING({NUMER,NN});//PARAMETERS NOT INTEGER   END;   IF NUMER<0 OR NN<0 THEN     RESULTS:=ReDIGITS(ABS(NUMER),ABS(NN));    RETURN IFTE((NUMER/NN)<0,"−"+RESULTS,RESULTS);   END;   //OK   //Step 0: reduce fraction   GD:=gcd(NUMER,NN);   RedNUMER:=NUMER/GD;   RedDENOM:=NN/GD;     //Continue...   //Get Length   //A possible optimisation:   //Avoid recalc    LST:=GetLEN(RedNUMER,RedDENOM);   //IF EXCESSIVE LENGTH RETURN NAN   IF NDIGITS>MIN(ImpRELEN,ImpSTRING-9) THEN //−9-ALLOW FOR DECSEP ETC    //STRING:TOO LONG TO GENERATE    //RELEN:USER LIMIT(TOO LONG/SLOW FOR USER)    RETURN STNANImp;    END;   //GetDecimalPlaces      //RP:=iquo((1*10^NDIGITS),NN);//works for repetends≤12digits:so use CAS     CAS("temporary:=iquo(((RedNUMER*10^NDIGITS),RedDENOM)");   ST:=CAS("string(temporary)");   //MSGBOX(ST);   STR:=ZEROS(NDIGITS-DIM(ST));   DP:=STR+ST;    //GetINTEGERPART   INTPART:=IFTE(RedDENOM,(IP(RedNUMER/RedDENOM)+DecSepNow()),DIVBY0);//THIS DIVBY IS GUARDED   //IF NUMER==1 THEN    //RECIPROCAL:iquo returns decimal places only   IF RedNUMER≠1 THEN //NN   //DEBUG;    //FRACTION: iquo returns IP and decimals with no point    IPLEN:=DIGITSNEEDED((IP(RedNUMER/RedDENOM)));//LEN OF IP    DP:=MID(DP,IPLEN+1); //DP   END;   //GetRepetend   REPETEND:=IFTE(RepetendLEN,MID(DP,TransientLEN+1),"");   //GetTransientDecimalPlaces   TRANSIENTPART:=IFTE(TransientLEN,LEFT(DP,TransientLEN),"");      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(NumerN,DenomN)  BEGIN   RETURN ReDIGITS(NumerN,DenomN);   END;  //Some call them Recurring  //Some call them Repeating  EXPORT Repeating(NumerN,DenomN)  BEGIN   RETURN ReDIGITS(NumerN,DenomN);  END;  GetTransient(NUMER,NN)  //NB Only when USCORE NOT EMPTY  //NB RECALCULATES  BEGIN   LOCAL ST:=ReDIGITS(NUMER,NN);   RETURN LEFT(ST,INSTRING(ST,USCORE));  END;  GetTransientToo(NUMER,NN,ST)  //Requires ST to supply digits an4 USCORE  BEGIN   RETURN LEFT(ST,INSTRING(ST,USCORE));   END;  EXPORT Show(NumerN,DenomN)  BEGIN     LOCAL PXP:={0};     LOCAL TRANSIENTPART;     LOCAL DST;     LOCAL KK,LST;     RECT_P();     TEXTOUT_P(CRID,0,0,3);     //TEXTOUT_P(ALGM,0,15,1);     TEXTOUT_P("Fraction,Reduced Fraction,Real,Decimal:",0,40);        // COMMON REPRESENTATIONS     TEXTOUT_P(NumerN+"/"+DenomN,0,60);     TEXTOUT_P(IFTE(DenomN,(NumerN/DenomN),(DIVBY0))+" Real",0,100);     //EARLY LENGTH     //Note:This is recalculated in ReDIGITS     LST:=GetLEN(NumerN,DenomN);     TEXTOUT_P("Has "+TransientLEN+" Transient digits & "+RepetendLEN+" Repetend digits",0,180);     TEXTOUT_P(RedNUMER+"/"+RedDENOM+" Reduced Fraction",0,80);          //Main Display     DST:=Recurring(NumerN,DenomN);     //TEXTOUT_P("Has "+TransientLEN+" Transient digits & "+RepetendLEN+" Repetend digits",0,180);//IF NOT EARLY        PXP(0):=TEXTOUT_P(DST+" Decimal",0,120);     TRANSIENTPART:=GetTransientToo(NumerN,DenomN,DST);      PXP(0):=TEXTOUT_P(TRANSIENTPART+" Transient Part",0,140);     IF INSTRING(DST,"00000000000000") THEN      //Loss Of significance suspected      TEXTOUT_P(" ! Check Possible Loss Of Significance !",0,200,3,RGB(255,0,0));     END;     IF MAX(PXP)≥320 THEN //OFFSCREEN      TEXTOUT_P("[View]",320*(4/6),220,3,RGB(255,0,0));     END;       TEXTOUT_P(IFTE(WAITS>0,"Wait...","[Esc]"),320*(5/6),220,3);       KK:=WAIT(WAITS);      IF KK==9 THEN //VIEW KEY      PRINT();      PRINT(NumerN+"/"+DenomN);      PRINT(LST);      PRINT(MID(DST,1,ImpPRINT));      IF DIM(DST)>ImpPRINT THEN       PRINT("PRINT Unable");//Or:Loop      END;      //WAIT(WAITS);     END;     RETURN DST;  END;  EXPORT ShowRange(Numer1,Numer2,Denom1,Denom2)  //Show range one by one  BEGIN   LOCAL II,JJ;   FOR II FROM Numer1 TO MAX(Numer2,Numer1) DO    FOR JJ FROM Denom1  TO MAX(Denom2,Denom1) DO     Show(II,JJ);    END;   END;  END;  EXPORT ShowReciprocals(FIRST,LAST)  BEGIN   LOCAL NN;   FOR NN FROM FIRST TO MAX(LAST,FIRST) DO    Show(1,NN);   END;  END;  EXPORT MultiplicativeOrder10(WhatsLeft)  //See http://www.hpmuseum.org/forum/thread-3212.html  // WHATSLEFT  BEGIN   LOCAL OKC:=0;   LOCAL AP:=0;   LOCAL NOTFND:=1;   LOCAL LST:={};//POSSIBLES TO CHECK      IF WhatsLeft≠1 THEN    //Get possibles    LST:=mat2list(idivis(euler(WhatsLeft)));    IF TYPE(LST)≠TYPE({}) THEN //EMPIRICAL TEST     //EG NN=1ᴇ14     OKC:=ZMSGBOX((ImpLimST+LST),OKC);     //PERHAPS RETURN AND HANDLE NAN INSTEAD     //IF NOT CAUGHT powmod WILL FAIL    END;    IF TYPE(LST)==TYPE({}) THEN     //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   END;//VALID LST   //Return 0 if WL=1 or no match   RETURN IFTE(NOTFND,0,LST(AP));  END;  EXPORT TESTS(TESTN)  //Perform some tests  BEGIN   LOCAL III,RR;   FOR III FROM 1 TO TESTN DO    //RECT_P();    //TEXTOUT_P(III,0,120);    TESTED:=III;    RR:=ReDIGITS(2,III);    //Note the biggest    IF TransientLEN>BigT THEN     BigT:=TransientLEN;    END;    IF RepetendLEN>BigR THEN     BigR:=RepetendLEN;    END;    DRAWMENU(III,BigT,BigR);//MAX    //DRAWMENU(III,TransientLEN,RepetendLEN);//CURRENT   END;  END;  TESTD()  BEGIN   LOCAL II;   FOR II FROM 1 TO 1000 DO    DIGITSNEEDED(123.4);   END;  END;  EXPORT REDECIMALS()  BEGIN   LOCAL TESTN:=1000;   ABOUT();    //HEADLINE RATE: LARGER WILL BE SLOWER   PRINT(TESTN+" fractions in "+TEVAL(TESTS(TESTN)));   //PRINT(DIM(Recurring(1,29989)));   //HELP();  END;

Some long repetends continue to incorrectly show all zeros.
Negative fractions may now cause a MultiplicativeOrder10 error message
Update: Some values are incorrect...

Stephen Lewkowicz (G1CMZ)
 « Next Oldest | Next Newest »

User(s) browsing this thread: 1 Guest(s)