Theses 2 programs are rounding a decimal value to the value of a fraction using Farey series. Use 'a b/c' key to display the fraction.
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;
VlE:= ABS(Vl);
DbN:= INT(VlE); DbD:=1; FnN:=DbN+1; FnD:=1;
RsN:= ROUND(VlE,0); RsD:= 1; RsE:= ABS(VlE-(RsN/RsD));
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)); END;
IF Tmp < VlE THEN DbN:= (DbN+FnN); DbD:= (DbD+FnD); ELSE FnN:= (DbN+FnN); FnD:= (DbD+FnD); END;
END;
RETURN SIGN(Vl)*RsN/RsD;
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:= INT(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 SIGN(Vl)*RsN/RsD;
END;