Post Reply 
Repeating Decimals / Recurring Decimals
02-01-2018, 05:53 PM (This post was last modified: 02-01-2018 07:14 PM by StephenG1CMZ.)
Post: #6
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 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
 
 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)
https://my.numworks.com/python/steveg1cmz
Visit this user's website Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
RE: Repeating Decimals - StephenG1CMZ - 01-21-2018, 11:01 AM
RE: Repeating Decimals / Recurring Decimals - StephenG1CMZ - 02-01-2018 05:53 PM



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