resueltos que punto online numericos normalizada norma metodos mantisa informatica flotante ejercicios ejemplos coma php math floating-point type-conversion rational-numbers

php - que - Conversión de decimal flotante a fracción



punto flotante metodos numericos (5)

Aquí está mi enfoque a este problema, funciona bien con números racionales. http://www.carlosabundis.com/2014/03/25/converting-decimals-to-fractions-with-php-v2/

function dec2fracso($dec){ //Negative number flag. $num=$dec; if($num<0){ $neg=true; }else{ $neg=false; } //Extracts 2 strings from input number $decarr=explode(''.'',(string)$dec); //Checks for divided by zero input. if($decarr[1]==0){ $decarr[1]=1; $fraccion[0]=$decarr[0]; $fraccion[1]=$decarr[1]; return $fraccion; } //Calculates the divisor before simplification. $long=strlen($decarr[1]); $div="1"; for($x=0;$x<$long;$x++){ $div.="0"; } //Gets the greatest common divisor. $x=(int)$decarr[1]; $y=(int)$div; $gcd=gmp_strval(gmp_gcd($x,$y)); //Calculates the result and fills the array with the correct sign. if($neg){ $fraccion[0]=((abs($decarr[0])*($y/$gcd))+($x/$gcd))*(-1); }else{ $fraccion[0]=(abs($decarr[0])*($y/$gcd))+($x/$gcd); } $fraccion[1]=($y/$gcd); return $fraccion; }

Estoy tratando de convertir los cálculos introducidos por los usuarios con los resultados decimales en fracciones. Por ejemplo; 66.6666666667 en 66 2/3. ¿Alguna sugerencia? Gracias por adelantado


Basado en la respuesta de @Joni, aquí es lo que usé para sacar el número completo.

function convert_decimal_to_fraction($decimal){ $big_fraction = float2rat($decimal); $num_array = explode(''/'', $big_fraction); $numerator = $num_array[0]; $denominator = $num_array[1]; $whole_number = floor( $numerator / $denominator ); $numerator = $numerator % $denominator; if($numerator == 0){ return $whole_number; }else if ($whole_number == 0){ return $numerator . ''/'' . $denominator; }else{ return $whole_number . '' '' . $numerator . ''/'' . $denominator; } } function float2rat($n, $tolerance = 1.e-6) { $h1=1; $h2=0; $k1=0; $k2=1; $b = 1/$n; do { $b = 1/$b; $a = floor($b); $aux = $h1; $h1 = $a*$h1+$h2; $h2 = $aux; $aux = $k1; $k1 = $a*$k1+$k2; $k2 = $aux; $b = $b-$a; } while (abs($n-$h1/$k1) > $n*$tolerance); return "$h1/$k1"; }


Código de Python convertido en respuesta de @ APerson241 a PHP

<?php function farey($v, $lim) { // No error checking on args. lim = maximum denominator. // Results are array(numerator, denominator); array(1, 0) is ''infinity''. if($v < 0) { list($n, $d) = farey(-$v, $lim); return array(-$n, $d); } $z = $lim - $lim; // Get a "zero of the right type" for the denominator list($lower, $upper) = array(array($z, $z+1), array($z+1, $z)); while(true) { $mediant = array(($lower[0] + $upper[0]), ($lower[1] + $upper[1])); if($v * $mediant[1] > $mediant[0]) { if($lim < $mediant[1]) return $upper; $lower = $mediant; } else if($v * $mediant[1] == $mediant[0]) { if($lim >= $mediant[1]) return $mediant; if($lower[1] < $upper[1]) return $lower; return $upper; } else { if($lim < $mediant[1]) return $lower; $upper = $mediant; } } } // Example use: $f = farey(66.66667, 10); echo $f[0], ''/'', $f[1], "/n"; # 200/3 $f = farey(sqrt(2), 1000); echo $f[0], ''/'', $f[1], "/n"; # 1393/985 $f = farey(0.43212, 2000); echo $f[0], ''/'', $f[1], "/n"; # 748/1731


Las fracciones Farey pueden ser bastante útiles en este caso.

Se pueden usar para convertir cualquier decimal en una fracción con el denominador más bajo posible.

Lo siento, no tengo un prototipo en PHP, así que aquí hay uno en Python:

def farey(v, lim): """No error checking on args. lim = maximum denominator. Results are (numerator, denominator); (1, 0) is ''infinity''.""" if v < 0: n, d = farey(-v, lim) return (-n, d) z = lim - lim # Get a "zero of the right type" for the denominator lower, upper = (z, z+1), (z+1, z) while True: mediant = (lower[0] + upper[0]), (lower[1] + upper[1]) if v * mediant[1] > mediant[0]: if lim < mediant[1]: return upper lower = mediant elif v * mediant[1] == mediant[0]: if lim >= mediant[1]: return mediant if lower[1] < upper[1]: return lower return upper else: if lim < mediant[1]: return lower upper = mediant


Las fracciones continuas se pueden usar para encontrar aproximaciones racionales a los números reales que son "mejores" en un sentido estricto. Aquí hay una función de PHP que encuentra una aproximación racional a un número de punto flotante (positivo) dado con un error relativo menor a $tolerance :

<?php function float2rat($n, $tolerance = 1.e-6) { $h1=1; $h2=0; $k1=0; $k2=1; $b = 1/$n; do { $b = 1/$b; $a = floor($b); $aux = $h1; $h1 = $a*$h1+$h2; $h2 = $aux; $aux = $k1; $k1 = $a*$k1+$k2; $k2 = $aux; $b = $b-$a; } while (abs($n-$h1/$k1) > $n*$tolerance); return "$h1/$k1"; } printf("%s/n", float2rat(66.66667)); # 200/3 printf("%s/n", float2rat(sqrt(2))); # 1393/985 printf("%s/n", float2rat(0.43212)); # 748/1731

He escrito más sobre este algoritmo y por qué funciona, e incluso una demostración de JavaScript aquí: http://jonisalonen.com/2012/converting-decimal-numbers-to-ratios/