Round a decimal value to fraction using Farey series - Printable Version

+- HP Forums (http://www.hpmuseum.org/forum)
+-- Forum: HP Software Libraries (/forum-10.html)
+--- Forum: HP Prime Software Library (/forum-15.html)
+--- Thread: Round a decimal value to fraction using Farey series (/thread-30.html)



Round a decimal value to fraction using Farey series - patrice - 12-11-2013 03:44 PM

FareyMax: Round Vl to best fraction with denominator smaller than DMax

FareyDelta: Round Vl to best fraction with Vl-Error < Fraction < Vl+Error



RE: Round a decimal value to fraction using Farey series - patrice - 06-06-2014 09:21 PM

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.