Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Странная работа функции ceil
Форумы портала PHP.SU » PHP » Программирование на PHP » Странная работа функции ceil

Страниц (2): [1] 2 »
 

1. dessor - 17 Февраля, 2011 - 20:05:10 - перейти к сообщению
Здравствуйте!

Есть небольшой скриптик (файл в приложении):
CODE (htmlphp):
скопировать код в буфер обмена
  1. <?php
  2. if($_POST['submit']) {
  3. $weight = '';
  4. $weight = strip_tags($_POST['weight']);
  5. $weight = floatval(str_replace(",", ".", $weight));
  6.  
  7. echo ceil($weight*100);
  8. }?>
  9. <form action="test.php" method="post">
  10.         <table cellspacing="5" cellpadding="0" border="0" valign="top" align="left">
  11.                 <tr>
  12.                         <td>
  13.                                 <input type="text" name="weight" size="5" value="<?php echo $weight;?>">
  14.                         </td>
  15.                         <td>
  16.                                 <input type="submit" value="Отправить" name="submit" >
  17.                         </td>
  18.                 </tr>
  19.         </table>
  20. </form>


Скрипт банальный. Так вот, если вводить "0.28", то результатом будет 29, если "1.28" будет 128, если "0.18" будет 18, если "0.38" будет 38.
Я не считаю себя крутым спецом в php программировании, но я уже года 4 на нем пишу сайты. С таким столкнулся не впервые, бывало нечто подобное и ранее. Раньше, выкручивался вводя дополнительные операции или чуть по другому составляя код.

Скажите, а как в таких случаях выкручиваются профессионалы? И что можно сделать в данном конкретном скрипте?
2. movEAX - 17 Февраля, 2011 - 20:21:33 - перейти к сообщению
php 5.3, тоже такая бага. Причем если передать просто 28, то все нормально.
3. dessor - 17 Февраля, 2011 - 20:46:22 - перейти к сообщению
в данном случае, php 5.2.7
Даже упростил:
CODE (htmlphp):
скопировать код в буфер обмена
  1. echo ceil(28);
  2. $a=0.28*100;
  3. echo '<br />'.ceil($a);

вверху 28, внизу 29 Не понял
4. grefon - 17 Февраля, 2011 - 21:07:11 - перейти к сообщению
Не понял Радость Прикол, ептель!

Вот так должно работать:
PHP:
скопировать код в буфер обмена
  1. echo ceil(28);
  2. $a=(int) ( 0.28*100 );
  3. echo '<br />'.ceil($a);
5. dessor - 17 Февраля, 2011 - 21:14:06 - перейти к сообщению
Да, так конечно работает) НО, задача фунции ceil теряется... а именно, округлять в большую сторону!
Т.е., если будет не 0.28, а 0.281, то должно получится именно 29.
6. grefon - 17 Февраля, 2011 - 21:22:27 - перейти к сообщению
Ок, а так?
PHP:
скопировать код в буфер обмена
  1. echo ceil(28);
  2. $a=floatval( 0.281*100 );
  3. echo '<br />'.ceil($a);
7. OrmaJever - 17 Февраля, 2011 - 21:33:51 - перейти к сообщению
Скорее всего что тип числа float вот оно и округляет. Если число целое оно должно быть int.
PHP:
скопировать код в буфер обмена
  1. $a=0.28*100;
  2. echo ceil((float)$a), '<br />';
  3. echo ceil((int)$a);
8. dessor - 17 Февраля, 2011 - 21:50:23 - перейти к сообщению
grefon, так функция ошибается...
OrmaJever, подход понятен, но для других то чисел все нормально! Я могу в своем скрипте сделать исключение для этого "28", но кто может утверждать, что оно одно такое?... никто Недовольство, огорчение
К тому же по мануалу функция ceil принимает тип float...

Ну хорошо, подскажите тогда, плиз, как реализовать округление числа до двух знаков после запятой другим способом?
9. OrmaJever - 17 Февраля, 2011 - 22:41:34 - перейти к сообщению
dessor пишет:
К тому же по мануалу функция ceil принимает тип float...

Ну вот поэтому она и округляет. Просто функция не ращитана на холостую работу (т.к. в 28 округлять нечего)
нужно поставить условие перед округлением и округлять только числа float is_float()
10. JustUserR - 18 Февраля, 2011 - 10:55:33 - перейти к сообщению
dessor пишет:
И что можно сделать в данном конкретном скрипте?
Действительной причиной осуществления нестабильного фунционирования операции округления в большую сторону в предполагаемого PHP-приложении является обеспечения трактования локальных числовых элементов в виде значений с плавающей точкой типа float - использование указанного метода трактования осуществляет формирование внутреннего представления числа с предварительной детерминированной погрешностью - обусловленность которой обеспечивается различием в конкретном значении десятичного числа и наиболее точным приближением комбинации элементов двоичной мантиссы и характеристического поля - таким образом для каждого из целых десятичных чисел типа N определенных в уровне float-трактования в действительности обеспечивается представление в виде N-eps или N+eps соответственно в зависимости исключительно от конкретного выбранного числа - что и осуществление выбор результата функционирования ceil-операции с недетерминированным исходом
dessor пишет:
Как в таких случаях выкручиваются профессионалы?
В качестве реального унифицированного метода решения предполагаемой задачи является использование десятичной арифметики - то есть осуществление операций с непосредственными десятичными тетрадами в десятично-двоичном коде
11. dessor - 18 Февраля, 2011 - 11:26:32 - перейти к сообщению
OrmaJever, к сожалению is_float воспринимает $a, именно как float... Код:
CODE (htmlphp):
скопировать код в буфер обмена
  1. $a=0.28*100;
  2. echo ceil((float)$a), '<br />';
  3. echo ceil((int)$a);
  4. echo '---//---';
  5.  
  6. if(is_float($a)) $weight = ceil($a);
  7. else $weight = (int)($a);
  8. echo $weight;


JustUserR, Круто . До такого уровня понимания php мне очень далеко)
Цитата:
с непосредственными десятичными тетрадами

Т.е. говоря простым языком, представлять числа в виде массива, как в модулях операций со сверхбольшими числами? Жесть. Этак, любая php-разработка с участием float поднимется в несколько раз в стоимости и столько же во времени...
Такие глюки только с float? С int все нормально?
(Добавление)
Собственно говоря правильно, что $a воспринимается как float - все корректно с точки зрения автоматического приведения типов php.
12. JustUserR - 18 Февраля, 2011 - 11:44:07 - перейти к сообщению
dessor пишет:
Т.е. говоря простым языком, представлять числа в виде массива, как в модулях операций со сверхбольшими числами? Жесть
Осуществление решения предполагаемой задачи на основе указанной метода в действительности требует высоких вычислительных ресурсов по причине требования выполнения ассоциированных команд процессора на уровня трактования исполняемого медленного приложения - однако реальной причиной возникнования указанного аспекта функционирования является некорректное использование типа данных float для хранения чисел с фиксированной точкой
dessor пишет:
Такие глюки только с float? С int все нормально?
Проявление рассматриваемых аспектов функционирования PHP-приложения в действительности осуществляется исключительно при использовании информационных полей расположенных в уровня трактования чисел с плавающей запятой типа float или double - дело в том что в случае применение целых чисел или элементов с фиксированной точкой целевое представление является либо фиксированным либо включает односторонную детерминированную поразрядную погрешность
13. dessor - 18 Февраля, 2011 - 19:36:43 - перейти к сообщению
JustUserR пишет:
однако реальной причиной возникнования указанного аспекта функционирования является некорректное использование типа данных float для хранения чисел с фиксированной точкой

А в чем заключается некорректность? И как правильно на данном примере использовать тип float? В идеале, с примером кода Улыбка
JustUserR пишет:
Проявление рассматриваемых аспектов функционирования PHP-приложения ... детерминированную поразрядную погрешность

Т.е., в int таких приколов быть неможет, правильно понял?
14. Champion - 18 Февраля, 2011 - 19:50:15 - перейти к сообщению
dessor пишет:
Т.е., в int таких приколов быть неможет, правильно понял?
Да, int будет правильно округляться до ближайшего большего целого)
dessor пишет:
До такого уровня понимания php мне очень далеко)
На самом деле, это уровень понимания того, как хранятся данные вещественных типов с плавающей точкой в компутере вообще. В любом языке программирования.
15. JustUserR - 19 Февраля, 2011 - 20:43:08 - перейти к сообщению
dessor пишет:
А в чем заключается некорректность? И как правильно на данном примере использовать тип float? В идеале, с примером кода
Использования информационных полей типа чисел с плавающей точкой осуществляет возможность хранения нецелых величин в условием обеспечения их хранения в виде максимального ближайшего приблежения в заданном контейнерком блоке - таким образом осуществление применение операции приведения числа типа float в целому элементу может производиться исключительно на основании анализа минимального отклонения - в то время как обеспечение корректного результата для функций типа floor/ceil не может гарантироваться
dessor пишет:
Т.е., в int таких приколов быть неможет, правильно понял?
Использование информационных полей типа int для хранения целых чисел и элементов с фиксированной точкой позволяет обеспечить формирование элемента с заданной точностью - таким образом осуществление последующего использование операции преобразования в целому числу обеспечивает получение гарантированного результата
В качестве конкретного примера позволяющего пояснить указанный аспект функционирования - возможно применение того факта что при использовании целочисленных величин производится безусловное размещение оригинального элемента в разрядной сетки - в то время как использование float-информационных полей предполагает осуществление поиска соответствующего элемента с минимальной погрешностью - расположение которого может произволиться как в области больших так и меньших чисел с равной вероятностью

 

Powered by ExBB FM 1.0 RC1