Post Reply 
Repeating Decimals / Recurring Decimals
01-24-2018, 07:21 PM
Post: #3
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 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.

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 - 01-24-2018 07:21 PM



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