PHP: перевести бесконечную периодическую дробь в обыкновенную
На самом деле, задачка вот такая:
Заданы натуральные величины
а, b, c
, гдеа
— целая часть вещественного числа,b
— дробная часть до периода,с
— период. Получить число в виде обыкновенной дроби видаm/n
, гдеm
— числитель,n
— знаменатель.
Суть в том, что некоторые дроби конечны, например, 1/4 = 0,25
, а некоторые - нет,
скажем, 1/3 = 0,3333333...
, это можно записать как тройку чисел (0,false,3)
- где 0
- целая часть, false
означает отсутствие части до периода (которая есть у других дробей, например, у 59/55 =
1,072727272... = (1, 0, 72)
часть до периода это "0
", отличаем от ситуации, когда её нет совсем,
как у 1/3
), а период это "3
".
По идее, реализация такова:
- сцепить цифры до периода и период в число
$d
; - получить число
$d2
, в котором столько девяток, сколько цифр в периоде дроби и затем столько нулей, сколько цифр до периода. Например, для(1, 791, 6)
получится9000
, т.к. в периоде одна цифра и три цифры до периода, для(2, false, 72)
получится99
, в периоде две цифры, а до периода цифр нет. Мы пользуемся "скользкими" преобразованиями вродеstrval(false)
ичисло - false
, но на данный момент в PHP 8 они работают корректно; - от числа
$d
отнять часть до периода$b
; - добавив в уменьшенный числитель
$d
целую часть$a
, полученное значение$d1
делим на$d2
, сократив дробь, получаем результат.
Вот написанный несколько второпях код, проверен на локальном хосте XAMPP с PHP8.
<?php function fraction ($a, $b, $c) { //целая часть, часть до периода, период $d = intval(strval($b).strval($c)); //цифры до периода и период числом $r = $d - $b; $clen = strlen(strval($c)); $d2 = ''; $d2 = str_pad($d2,$clen,'9'); if ($b !== false) { $blen = strlen(strval($b)); $d2 = intval(str_pad($d2,$clen+$blen,'0')); } $d -= $b; $d1 = $a * $d2 + $d; $gcd = gmp_gcd($d1, $d2); $d1 /= $gcd; $d2 /= $gcd; return $d1.'/'.$d2; } echo fraction (2, false, 72); //30/11 - части до периода нет echo '<br>'.fraction (5, false, 3); //5 1/3 = 16/3 echo '<br>'.fraction (1, 791, 6); //43/24 echo '<br>'.fraction (0, 6, 428571); //9/14 echo '<br>'.fraction (1, 0, 72); //59/55 - часть до периода именно "0" ?>
В активном файле php.ini
должно быть включено расширение GMP (убрать точку с запятой в строке
;extension=gmp
и перезапустить web-сервер). Узнать, где находится активный файл php.ini
можно, выполнив это
<?php phpinfo(); ?>
и прочитав ответ в строке таблицы "Loaded Configuration File".
При желании легко написать и собственную реализацию функции gcd.
05.12.2021, 17:48 [750 просмотров]