БлогNot. PHP: сократить дробь или найти её примерное десятичное представление

PHP: сократить дробь или найти её примерное десятичное представление

Вот здесь я подбирал "близкие" дроби довольно громоздким перебором, зато скрипт может сказать, что дробь 335/1095 отличается от 26/85 менее, чем на 1/1000.

Правда, я не помню, почему исключил из подбора близких дробей числители и знаменатели, равные 10, 100 или 1000.

Чтобы это убрать, достаточно заменить в исходнике строку

if (ch1!=z1 && !(ch1==1 || ch1==10 || ch1==100 || ch1==1000 || z1==1 || z1==10 || z1==100 || z1==1000))

на

if (ch1!=z1)

В приведённом ниже учебном примере стояла более скромная задача - просто сократить дробь, если есть такая возможность (наибольшее число, на которое можно поделить числитель и знаменатель дроби, равно НОД от пары значений (числитель, знаменатель)). На всякий случай добавлено и "примерное округление", но не такое как в скрипте по ссылке - функция error($er) просто представляет дробь как число, числитель и знаменатель которого не превышают 10 в степени $er.

Вот код класса-примера, сделать для него оболочку нетрудно. Обратите внимание, что и cut, и error пишут в приватные свойства класса, то есть, значение дроби после их вызова меняется.

<?php
class Fraction { //Дробь
 private $ch,$zn; //Числитель и знаменатель
 function __construct ($ch=1,$zn=1) { //конструктор
  $this->ch =  abs(intval($ch)); $this->zn =  abs(intval($zn));
 }
 function get() { //Вернуть дробь строкой вида "12/34"
  return ( $this->zn == 0 ? '&infin;' : 
   ($this->ch==$this->zn ? '1' : $this->ch.'/'.$this->zn) ); 
 }
 private function nod($ch,$zn) { //Найти НОД
  return ($ch ? $this->nod($zn%$ch,$ch) : $zn);
 }
 function cut() { //Сократить, если есть НОД>1
  $nod = $this->nod($this->ch,$this->zn);
  if ($nod>1) { $this->ch/=$nod; $this->zn/=$nod; }
 }
 function dec($signs=3) { //Десятичное представление с $signs знаками в дробной части (округление)
  return ($this->zn == 0 ? '&infin;' : round($this->ch/$this->zn,$signs));
 }
 function error($er=1) { 
  //Примерное десятичное представление дробью $er степени десятки ($er>0), вернёт оценку погрешности
  if ($this->zn == 0) return '&infin;';
  $dec = $this->ch/$this->zn;
  $dec2 = preg_replace("/^(.*[,\.]\d{0,".$er."}).*$/","$1","$dec");
  $this->ch=$dec2*pow(10,$er); 
  $this->zn=pow(10,$er); 
  return round(abs($dec-$this->ch/$this->zn),$er);
 }
}                 
$n = new Fraction(24,36);
echo '<br>Исходная дробь: '.$n->get();
$n->cut();
echo '<br>Сокращённая дробь: '.$n->get();
echo '<br>В десятичном виде: '.$n->dec();
$e=$n->error(1);
echo '<br>Приблизительно равно: '.$n->get().' с погрешностью '.$e;
?>

Конструктор класса делает переданные в него значения числителя и знаменателя натуральными числами, методы учитывают, что числитель и знаменатель могут совпадать или в знаменателе может оказаться ноль.

Любопытно в коде разве то, как в функции error оставлено (не округлено) $er знаков в дробной части числа с помощью стандартной preg_replace.

Вывод этого примера:

Исходная дробь: 24/36
Сокращённая дробь: 2/3
В десятичном виде: 0.667
Приблизительно равно: 6/10 с погрешностью 0.1

26.02.2016, 20:40 [6711 просмотров]


теги: учебное php числа

К этой статье пока нет комментариев, Ваш будет первым