БлогNot. PHP: "инновационный" калькулятор или считаем всё сразу :)

PHP: "инновационный" калькулятор или считаем всё сразу :)

Зачем делать лишние клики? Вво-о-одим число, выбира-а-аем операцию, второ-ое число, да ещё и "равно" или Enter. Километровый пробег мыши или пальцев :) Почему не сделать так: ввести число, нажать клавишу TAB, ввести второе число, нажать Enter, и всё сразу посчитано - арифметические действия, степень и корень, тригонометрические функции, экспонента и логарифмы, ну, можно ещё полярные кооррдинаты, проценты, а для целых значений - количество сочетаний и перестановок.

На самом деле, конечно, шучу. Это очередной учебный, а если мне повезёт, то и завершающий серию скрипт на PHP. Писался, в основном, для иллюстрации проверки ошибок при вычислениях конструкциями вида

if (is_nan($r) or is_infinite($r)) return ERROR;

- "если получено не число или бесконечность". Ну и ещё полезные мелочи можно в исходнике найти.

 Скрипт в работе

Вызывается также "напрямую" методом GET, например, вот так. Думаю, параметры хорошо видны из адресной строки:

  • x=число и y=число - первый и второй операнды формул. Для отделения дробной части от целой можно использовать и запятую вместо точки, скрипт это исправит;
  • signs=число - целое количество знаков в дробной части, допустимы значения от -1 до константы PRESITION-1 включительно, -1 означает "не округлять", 0 - округлять до целых, 1 - оставлять 1 знак в дробной части и т.д.;
  • action=1 - чтобы всё сразу вычислилось, иначе просто заполнятся поля ввода.

Исходник на момент написания приводится ниже. В нём жертвуется сестра таланта во имя тупочитабельности.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
 <meta content="text/html; charset=Windows-1251" http-equiv="content-type">
 <title>Калькулятор с 2 операндами</title>
</head>
<body>

<?php
 error_reporting(E_ERROR);
 define ('PRESITION','9'); //предельное число знаков в дробной части + 1
 define ('ERROR','Ошибка!');  //сообщение об ошибке

 function trimall($string) { 
  $string = str_replace(",",".",trim($string));
  return preg_replace("/(^\s*)|(\s*$)/","",preg_replace("/\s+/"," ",$string));
 }
 
 function magic ($path) {
  @ini_set('magic_quotes_runtime', '0'); @ini_set('magic_quotes_sybase', '0');
  return (@get_magic_quotes_gpc()=='1' ? stripslashes($path) : $path);
 }

 function get_word_form ($n,$word,$o1,$o2,$o5) {
  //Получить нормальное окончание для слова $word и числа объектов $n.
  //Параметры:
  //$o1 - окончание для числа *1, 
  //$o2 - окончание для *2-*4, 
  //$o5 - окончание для чисел *5-*9,*0,*11-*19
  if ($n%100>10 and $n%100<20 or $n%10==0 or $n%10>4) $word.=$o5;
  else if ($n%10>1 and $n%10<5) $word.=$o2;
  else $word.=$o1;
  return $word;
 }
 
 $params = array ('x','y','signs','action');
 while (list($num,$var) = each($params)) {
  if (!empty($_POST[$var])) $$var = floatval(trimall(htmlspecialchars(magic($_POST[$var]))));
  else if (!empty($_GET[$var])) $$var = floatval(trimall(htmlspecialchars(magic($_GET[$var]))));
  else $$var = ($var=='signs' ? '-1' : '0');
 }

 if (is_nan($x) or is_infinite($x)) $x=0; 
 if (is_nan($y) or is_infinite($y)) $y=0; 
 $signs=intval($signs);
 if (is_nan($signs) or is_infinite($signs)) $signs=-1; 
 if ($signs<-1) $signs=-1;
 if ($signs>PRESITION-1) $signs=PRESITION-1;

 $result='';
 if (!empty($action)) {
  $result = '<table align="center" border="0" cellpadding="3" cellspacing="0">
   <tr>
    <td colspan="2" align="center" valign="middle"><b>Арифметика</b></td>
   <tr>
   <tr>
    <td>'.r_($x,$signs).'+'.($y<0?'(':'').r_($y,$signs).($y<0?')':'').' = '.plus($x,$y,$signs).'</td>
    <td>'.r_($x,$signs).'-'.($y<0?'(':'').r_($y,$signs).($y<0?')':'').' = '.minus($x,$y,$signs).'</td>
   </tr>
   <tr>
    <td>'.r_($x,$signs).'*'.r_($y,$signs).' = '.multiply($x,$y,$signs).'</td>
    <td>'.r_($x,$signs).'/'.r_($y,$signs).' = '.divide($x,$y,$signs).'</td>
   </tr>
   <tr>
    <td colspan="2" align="center" valign="middle"><b>Деление нацело и остаток от деления</b></td>
   <tr>
   <tr>
    <td>'.i_($x).' div '.i_($y).' = '.div($x,$y).'</td>
    <td>'.i_($x).' mod '.i_($y).' = '.mod($x,$y).'</td>
   </tr>
   <tr>
    <td colspan="2" align="center" valign="middle"><b>Степень и квадратный корень</b></td>
   <tr>
   <tr>
    <td>'.$x.'<sup>'.$y.'</sup> = '.power($x,$y,$signs).'</td>
    <td>&radic;<span style="text-decoration: overline;">'.$x.'</span> = '.sqrt_($x,$signs).'</td>
   </tr>
   <tr>
    <td colspan="2" align="center" valign="middle"><b>Тригонометрия</b></td>
   <tr>
   <tr>
    <td>sin('.$x.' рад) = '.sin_($x,'rad',$signs).'</td>
    <td>sin('.$x.'&deg;) = '.sin_($x,'deg',$signs).'</td>
   </tr>
   <tr>
    <td>cos('.$x.' рад) = '.cos_($x,'rad',$signs).'</td>
    <td>cos('.$x.'&deg;) = '.cos_($x,'deg',$signs).'</td>
   </tr>
   <tr>
    <td>tan('.$x.' рад) = '.tan_($x,'rad',$signs).'</td>
    <td>tan('.$x.'&deg;) = '.tan_($x,'deg',$signs).'</td>
   </tr>
   <tr>
    <td colspan="2" align="center" valign="middle"><b>Полярные координаты</b></td>
   <tr>
   <tr>
    <td>&rho;('.$x.','.$y.') = '.rho($x,$y,$signs).'</td>
    <td>&phi;('.$x.','.$y.') = '.phi($x,$y,$signs).'</td>
   </tr>
   <tr>
    <td colspan="2" align="center" valign="middle"><b>Экспонента и логарифмы</b></td>
   <tr>
   <tr>
    <td>exp('.$x.') = '.exp_($x,$signs).'</td>
    <td>ln('.$x.') = '.ln_($x,$signs).'</td>
   </tr>
   <tr>
    <td>log<sub>10</sub>'.$x.' = '.log10_($x,$signs).'</td>
    <td>log<sub>'.$y.'</sub>'.$x.' = '.log_($x,$y,$signs).'</td>
   </tr>
   <tr>
    <td colspan="2" align="center" valign="middle"><b>Сочетания и перестановки</b></td>
   <tr>
   <tr>
    <td>'.i_($x).'! = '.fact($x).'</td>
    <td>'.i_($y).'! = '.fact($y).'</td>
   </tr>
   <tr>
    <td colspan="2">Сочетаний из '.i_($x).' по '.i_($y).' (порядок объектов неважен) = '.soch($x,$y).'</td>
   </tr>
   <tr>
    <td colspan="2">Перестановок из '.i_($x).' по '.i_($y).' (порядок объектов важен) = '.perest($x,$y).'</td> 
   </tr>
   <tr>
    <td colspan="2" align="center" valign="middle"><b>Проценты</b></td>
   <tr>
   <tr>
    <td>'.$y.'% от '.$x.' = '.ps1($x,$y,$signs).'</td>
    <td>Значение '.$x.' в % от '.$y.' = '.ps2($x,$y,$signs).'%</td>
   </tr>
  </table>'."\n";
 }
 echo '
 <script type="text/javascript">
  function clearme() {
   document.f1.x.value = ""; document.f1.y.value = "";  
   document.getElementById("result").innerHTML = "";
   document.f1.signs.selectedIndex = 0;
  }
 </script>
 <noscript>
  <div align="center"><small>Кнопка Очистить и автовыделение полей не будут работать 
    из-за выключенного в вашем браузере Javascript!</small></div>
 </noscript>

 <form name="f1" method="post" action="'.$_SERVER['PHP_SELF'].'">
  <table align="center" border="0" cellpadding="3" cellspacing="0">
   <tr>
    <td align="right">X=</td>
    <td>
     <input type="text" name="x" maxlength="'.(PRESITION+2).'" size="'.
      (PRESITION+4).'" value="'.$x.'" onclick="this.select();">
    </td>
    <td align="right">Y=</td>
    <td>
     <input type="text" name="y" maxlength="'.(PRESITION+2).'" size="'.
      (PRESITION+4).'" value="'.$y.'" onclick="this.select();">
    </td>
   <tr>
    <td colspan="2">';
 echo '<select name="signs" size="1">'."\n";
 echo '<option value="-1"'.($signs==-1?' selected':'').'>Не округлять'."\n";
 for ($i=0; $i<PRESITION; $i++)
  echo '<option value="'.$i.'"'.($signs==$i?' selected':'').'>'.$i.' '.get_word_form ($i,'знак','','а','ов')."\n";
 echo '</select>'."\n"; 
 echo '
    </td>
    <td colspan="2">
     <input type="hidden" name="action" value="1"> 
     <input type="submit" value="Вычислить"> 
     <input type="button" value="Очистить" onclick="clearme();">
    </td>
   </tr>
  </table>
 </form>'."\n".'
 <script type="text/javascript">
  function start() { document.f1.x.select(); }
  start();
 </script>
 <table align="center" border="0" cellpadding="4" cellspacing="0">
   <tr>
    <td><div id="result">'.$result.'</div></td>
    </td>
   </tr>
  </table>'."\n";

 function r_($x,$signs) {
  return $signs==-1 ? $x : round($x,$signs);
 }
 function i_($x) {
  $r=intval($x);
  if (is_nan($r) or is_infinite($r)) return 0;
  else return $r;
 }
 function plus ($x,$y,$signs) {
  $r = $x+$y;
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function minus ($x,$y,$signs) {
  $r = $x-$y;
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function multiply ($x,$y,$signs) {
  $r = $x*$y;
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function divide ($x,$y,$signs) {
  if (!$y) return ERROR;
  $r = $x/$y;
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function div ($x,$y) {
  if (!$y) return ERROR;
  return intval($y) ? floor(intval($x)/intval($y)) : ERROR;
 }
 function mod ($x,$y) {
  if (!$y) return ERROR;
  return intval($y) ? intval($x)%intval($y) : ERROR;
 }
 function power ($x,$y,$signs) {
  $r = pow($x,$y);
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function sqrt_ ($x,$signs) {
  $r = sqrt($x);
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function sin_ ($x,$measure,$signs) {
  $r = $measure=='rad' ? sin($x) : sin(deg2rad($x));
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function cos_ ($x,$measure,$signs) {
  $r = $measure=='rad' ? cos($x) : cos(deg2rad($x));
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function tan_ ($x,$measure,$signs) {
  $p = -1*(PRESITION-1);
  if ($measure=='rad' and abs(cos($x))<pow(10,$p)) return ERROR;
  if ($measure=='deg' and abs(cos(deg2rad($x)))<pow(10,$p)) return ERROR;
  $r = $measure=='rad' ? tan($x) : tan(deg2rad($x));
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function rho ($x,$y,$signs) {
  $r = sqrt(pow($x,2)+pow($y,2));
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function phi ($x,$y,$signs) {
  $r = atan2($y,$x);
  if (is_nan($r) or is_infinite($r)) return ERROR;
  if ($signs==-1) return $r.' ('.rad2deg($r).'&deg;)';
  else return round($r,$signs).' ('.round(rad2deg($r),$signs).'&deg;)';
 }
 function exp_ ($x,$signs) {
  $r = exp($x);
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function ln_ ($x,$signs) {
  $r = log($x);
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function log10_ ($x,$signs) {
  $r = log10($x);
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function log_ ($number,$base,$signs) {
  $r = log($number) / log($base);
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function fact($n) {
  $n = intval($n);
  if ($n<0 or is_nan($n) or is_infinite($n)) return ERROR;  
  $r = 1;
  for ($index = 1; $index <= $n; $index++) {
   $r *= $index;
   if (is_nan($r) or is_infinite($r)) return ERROR;  
  }
  return $r;
 }
 function soch ($x,$y) {
  if ($x<0 or $y<0 or $x<$y or is_nan(intval($x)) or is_nan(intval($y))) return ERROR;
  $f1 = fact($x);
  $f2 = fact($y);
  $f3 = fact(i_($x)-i_($y));
  if ($f1==ERROR or $f2==ERROR or $f3==ERROR) return ERROR;
  $r =  $f1 / ($f2*$f3);
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $r;
 }
 function perest ($x,$y) {
  if ($x<0 or $y<0 or $x<$y or is_nan(intval($x)) or is_nan(intval($y))) return ERROR;
  $f1 = fact($x);
  $f3 = fact(i_($x)-i_($y));
  if ($f1==ERROR or $f3==ERROR) return ERROR;
  $r = $f1 / $f3;
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $r;
 }
 function ps1 ($x,$y,$signs) {
  $r = $y*$x/100;
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
 function ps2 ($x,$y,$signs) {
  $r = $x/$y*100;
  if (is_nan($r) or is_infinite($r)) return ERROR;
  return $signs==-1 ? $r : round($r,$signs);
 }
?>
</body></html>

02.03.2016, 18:45 [7359 просмотров]


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

показать комментарии (1)