PDA

View Full Version : Decimal To Fraction [0.5=1/2] ActionScript Algorithm


marlopax
09-14-2011, 09:13 AM
Lot of times I saw people asking for decimal conversion algorithm in ActionScript or want to know the logic behind it. So, I decided to share my algorithm to those who need this for there development purposes.
This code is OS and you are free to use in any manner you like.


/**
*author : MarlöPax
*created : 09.14.2011.
*location : India.
*usage : decimal to factor.
*/

function marlopaxDF(denominatorX,numaretorX=10):String {
var strLen:String=denominatorX.toString().split(".")[1].length;
var numaretor=1;
for (var z=0; z<strLen; z++) {
numaretor*=numaretorX;
}
var denominator=denominatorX*numaretor;
var arr:Array=new Array();
for (var i=1; i<=numaretor; i++) {
var n=denominator/i;
var r=Math.round(n);
if (n==r) {
if (n/numaretor==r/numaretor) {
var den=denominator/n;
var num=numaretor/r;
if (den==Math.round(den) && num==Math.round(num)) {
var fRD=den;
var fRN=num;
arr.push({frd:fRD,frn:fRN});
}
}
}
}
return arr[0].frd + "/" + arr[0].frn;
}

trace(marlopaxDF(.25)); // Put you query here.


Hope this will help someone.



marlopax

-:)lauri
01-19-2012, 01:42 AM
fantastic :)

I found javascript solution (http://www.mindspring.com/~alanh/fracs.html) and it worked in like actionscript file as if it was made with it. Well I made few changes and parsed the answer I liked most out:

function approximateFractions(d:Number):String {
var numerators = [0, 1];
var denominators = [1, 0];
var maxNumerator = getMaxNumerator(d);
var d2 = d;
var calcD, prevCalcD = NaN;
for (var i = 2; i < 1000; i++) {
var L2 = Math.floor(d2);
numerators[i] = L2 * numerators[i-1] + numerators[i-2];
if (Math.abs(numerators[i]) > maxNumerator) return undefined;
denominators[i] = L2 * denominators[i-1] + denominators[i-2];
calcD = numerators[i] / denominators[i];
if (calcD == prevCalcD) return undefined;
var answer:String = outPut(d, numerators[i], denominators[i]);
if(answer) {
i = 1000;
return answer;
}
if (calcD == d) return undefined;
prevCalcD = calcD;
d2 = 1/(d2-L2);
}
return undefined;
}



function getMaxNumerator(f){
var f2 = null;
var ixe = f.toString().indexOf("E");
if (ixe==-1) ixe = f.toString().indexOf("e");
if (ixe == -1) f2 = f.toString();
else f2 = f.toString().substring(0, ixe);
var digits = null;
var ix = f2.toString().indexOf(".");
if (ix==-1) digits = f2;
else if (ix==0) digits = f2.substring(1, f2.length);
else if (ix < f2.length) digits = f2.substring(0, ix) + f2.substring(ix + 1, f2.length);
var L = digits;
var numDigits = L.toString().length;
var L2 = f;
var numIntDigits = L2.toString().length;
if (L2 == 0) numIntDigits = 0;
var numDigitsPastDecimal = numDigits - numIntDigits;
for (var i=numDigitsPastDecimal; i>0 && L%2==0; i--) L/=2;
for (var j=numDigitsPastDecimal; j>0 && L%5==0; j--) L/=5;
return L;
}

function outPut(input:Number, nums:Number, denoms:Number):String{
var a:Array = String(input).split(".");
var b:Array = String(nums/denoms).split(".");
if(!isNaN(Number(a[0])) && !isNaN(Number(a[1])) && !isNaN(Number(b[0])) && !isNaN(Number(b[1]))) {
if(a[0] == b[0] && a[1] == b[1].substring(0,a[1].length)) {
return String(nums+"/"+denoms);
}
}
return undefined;
}

trace(approximateFractions(0.33333333333333)); // -> 1/3
trace(approximateFractions(5.666)); // -> 17/3
trace(approximateFractions(123.123)); // -> 8003/65

-:)lauri
01-19-2012, 02:19 AM
in this part the return value should be of course the original value the user has inputted

if(answer) {
i = 1000;
return answer;
}
if (calcD == d) return undefined; // change undefined to d
prevCalcD = calcD;
d2 = 1/(d2-L2);

marlopax
01-19-2012, 04:56 AM
This is Great to see someone added more solutions.

Thank You lauri.


Regards



marlopax

wvxvw
02-01-2012, 03:32 PM
Below is a bit different algorithm. It, however, doesnt' do "fuzzy" rounding. That is 0.33333333333 will not give you 1/3, but 0.725 will give you 29/40.

public static function floatToRational(float:Number):Vector.<Number>
{
var orders:Number = 1;
var steps:int;
var result:Vector.<Number> = new Vector.<Number>(2, true);
var denominator:int;

while ((float *= 10) <= 0) steps--;
while ((float *= 10) % 10 >= 0.1) steps++;
result[0] = Math.floor(float / 10);
result[1] = Math.pow(10, steps + 1);
denominator = _gcd(result[0], result[1]);
result[0] = Math.round(result[0] / denominator);
result[1] = Math.round(result[1] / denominator);
return result;
}

public static function gcd(...integers):int
{
var i:int = integers.length - 1;
var result:int = integers[integers.length - 1];

if (i > 0) while (--i >= 0) result = _gcd(integers[i], result);
return result;
}

private static function _gcd(a:int, b:int):int
{
var divident:int = Math.max(a, b);
var divisor:int = Math.min(a, b);
var quotient:int = divident / divisor;
var remainder:int = divident - quotient * divisor;
var result:int;

if (remainder) result = _gcd(b, remainder);
else result = divisor;
return result;
}