Дробь в десятичную дробь довольно проста, и существует множество решений. Я бы пошел с обрезкой строки, заменой пробелов на «+» и всего, кроме пробела, / ,. или цифры с '', а затем запустить его через 'eval'.
Десятичные дроби практически невозможно сделать правильно - не в последнюю очередь потому, что ваша десятичная дробь, вероятно, должна быть сначала преобразована в двоичную - в этот момент вы теряете большую точность. В качестве академического упражнения ..... Если вы можете жить с разницей между 20976/41953 и 1/2, то вы можете попробовать нечеткое совпадение для заранее определенного числа фракций:
(возможно, есть более удобный способ реализации того же алгоритма, но я оставлю это в качестве упражнения для читателя).
define('DECIMAL_DIGITS',5);
function decimal_2_frac($inp_decimal)
{
static $fracs;
if (!is_array($fracs)) {
init_fracs($fracs);
}
$int_part=(integer)$inp_decimal;
$inp_decimal=$inp_decimal-$int_part;
$candidate='';
$distance=10;
foreach ($fracs as $decimal=>$frac) {
if (abs($decimal-$inp_decimal)<$distance) {
$candidate=$frac;
$distance=abs($decimal-$inp_decimal);
}
if (abs($decimal-$inp_decimal)>$distance) {
break;
}
}
return $int_part . ' ' . $candidate;
}
function init_fracs(&$fracs)
{
$fracs=array();
for ($x=2;$x<(5*DECIMAL_DIGITS);$x++) {
// there's probably a beter way to calculate the loop limit
for ($y=1; $y<$x; $y++) {
$decimal=round($y/$x,DECIMAL_DIGITS);
$frac="$x/$y";
if (!array_key_exists($decimal,$fracs)) {
$fracs[$decimal]=$frac;
}
}
}
}
Но лично я бы просто сохранил исходное представление в отдельном поле в базе данных.