Post Reply 
Round a decimal value to fraction using Farey series
06-07-2014, 02:21 AM (This post was last modified: 06-17-2014 12:44 AM by patrice.)
Post: #5
RE: Round a decimal value to fraction using Farey series
Update for Rev 6030
Code:
#pragma mode( separator(.,;) integer(h64) )
// rev 6030 update
EXPORT RoundFract(V, F)
BEGIN
RETURN ROUND(V*F,0)/F;
END;

EXPORT FareyMax(Vl, DMax)
// Round a Vl to the best fraction with denominator < DMax
BEGIN
LOCAL VlE, Tmp;
LOCAL DbN,DbD, FnN,FnD, RsN,RsD,RsE;
PRINT();
VlE:= ABS(Vl);
DbN:= IP(VlE); DbD:=1; FnN:=DbN+1; FnD:=1;
RsN:= ROUND(VlE,0); RsD:= 1; RsE:= ABS(VlE-(RsN/RsD));
PRINT(STRING(SIGN(Vl)*RsN,2,0)+"/"+STRING(RsD,2,0));
WHILE DbD+FnD <= DMax DO
  Tmp:= (DbN+FnN)/(DbD+FnD);
  IF RsE > ABS(VlE-Tmp) THEN RsN:= (DbN+FnN); RsD:= (DbD+FnD); RsE:= ABS(VlE-(RsN/RsD)); PRINT(STRING(SIGN(Vl)*RsN,2,0)+"/"+STRING(RsD,2,0));END;
  IF Tmp < VlE THEN DbN:= (DbN+FnN); DbD:= (DbD+FnD); ELSE FnN:= (DbN+FnN); FnD:= (DbD+FnD); END;
END;
// RETURN "'"+STRING(SIGN(Vl)*RsN,2,0)+"/"+STRING(RsD,2,0)+"'";
RETURN EXPR("QUOTE("+STRING(SIGN(Vl)*RsN,2,0)+"/"+STRING(RsD,2,0)+")");
END;

EXPORT FareyDelta(Vl, Error)
// round Vl to the smallest fraction with |Vl - fraction| < Error
BEGIN
LOCAL VlE, Tmp;
LOCAL DbN,DbD, FnN,FnD, RsN,RsD,RsE;
VlE:= ABS(Vl);
DbN:= IP(VlE); DbD:=1; FnN:=DbN+1; FnD:=1;
RsN:= ROUND(VlE,0); RsD:= 1; RsE:= ABS(VlE-(RsN/RsD));
WHILE RsE > Error DO
  Tmp:= (DbN+FnN)/(DbD+FnD);
  IF RsE > ABS(VlE-Tmp) THEN RsN:= (DbN+FnN); RsD:= (DbD+FnD); RsE:= ABS(VlE-(RsN/RsD)); END;
  IF Tmp < VlE THEN DbN:= (DbN+FnN); DbD:= (DbD+FnD); ELSE FnN:= (DbN+FnN); FnD:= (DbD+FnD); END;
END;
// RETURN "'"+STRING(SIGN(Vl)*RsN,2,0)+"/"+STRING(RsD,2,0)+"'";
RETURN EXPR("QUOTE("+STRING(SIGN(Vl)*RsN,2,0)+"/"+STRING(RsD,2,0)+")");
END;

EXPORT FareyDisp(Vl,Rnd)
// round Vl to the smallest fraction that match the display
BEGIN
LOCAL VlE, Tmp;
LOCAL DbN,DbD, FnN,FnD, RsN,RsD,RsE;
VlE:= ABS(ROUND(Vl,Rnd));
DbN:= IP(VlE); DbD:=1; FnN:=DbN+1; FnD:=1;
RsN:= ROUND(VlE,0); RsD:= 1; RsE:= ABS(VlE-ROUND(RsN/RsD,Rnd));
WHILE RsE > 0 DO
  Tmp:= (DbN+FnN)/(DbD+FnD);
  IF RsE > ABS(VlE-Tmp) THEN RsN:= (DbN+FnN); RsD:= (DbD+FnD); RsE:= ABS(VlE-ROUND(RsN/RsD,Rnd)); END;
  IF Tmp < VlE THEN DbN:= (DbN+FnN); DbD:= (DbD+FnD); ELSE FnN:= (DbN+FnN); FnD:= (DbD+FnD); END;
END;
RETURN EXPR("QUOTE("+STRING(SIGN(Vl)*RsN,2,0)+"/"+STRING(RsD,2,0)+")");
END;
Nota: if you want FareyMax to be a simple function, just remove all PRINT commands from source code.

Patrice
“Everything should be made as simple as possible, but no simpler.” Albert Einstein
Find all posts by this user
Quote this message in a reply
Post Reply 


Messages In This Thread
RE: Round a decimal value to fraction using Farey series - patrice - 06-07-2014 02:21 AM



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