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

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Странная работа функции ceil

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


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

> Описание: я не профи, помогите, пожалуйста.
dessor
Отправлено: 17 Февраля, 2011 - 20:05:10
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Февр. 2011  


Помог: 0 раз(а)




Здравствуйте!

Есть небольшой скриптик (файл в приложении):
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 на нем пишу сайты. С таким столкнулся не впервые, бывало нечто подобное и ранее. Раньше, выкручивался вводя дополнительные операции или чуть по другому составляя код.

Скажите, а как в таких случаях выкручиваются профессионалы? И что можно сделать в данном конкретном скрипте?
Скачать файл: test.php
Скачан раз: 106

(Отредактировано автором: 17 Февраля, 2011 - 21:10:23)

 
 Top
movEAX
Отправлено: 17 Февраля, 2011 - 20:21:33
Post Id



Частый посетитель


Покинул форум
Сообщений всего: 750
Дата рег-ции: Авг. 2009  


Помог: 16 раз(а)




php 5.3, тоже такая бага. Причем если передать просто 28, то все нормально.


-----
армия.. самое убогое место
 
 Top
dessor
Отправлено: 17 Февраля, 2011 - 20:46:22
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Февр. 2011  


Помог: 0 раз(а)




в данном случае, php 5.2.7
Даже упростил:
CODE (htmlphp):
скопировать код в буфер обмена
  1. echo ceil(28);
  2. $a=0.28*100;
  3. echo '<br />'.ceil($a);

вверху 28, внизу 29 Не понял

(Отредактировано автором: 17 Февраля, 2011 - 20:46:44)

 
 Top
grefon
Отправлено: 17 Февраля, 2011 - 21:07:11
Post Id



Частый посетитель


Покинул форум
Сообщений всего: 823
Дата рег-ции: Нояб. 2010  


Помог: 32 раз(а)




Не понял Радость Прикол, ептель!

Вот так должно работать:
PHP:
скопировать код в буфер обмена
  1. echo ceil(28);
  2. $a=(int) ( 0.28*100 );
  3. echo '<br />'.ceil($a);


-----
____________________________________________________________________
Ну как то так, наверное.
http://grefon[dot]com
 
 Top
dessor
Отправлено: 17 Февраля, 2011 - 21:14:06
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Февр. 2011  


Помог: 0 раз(а)




Да, так конечно работает) НО, задача фунции ceil теряется... а именно, округлять в большую сторону!
Т.е., если будет не 0.28, а 0.281, то должно получится именно 29.

(Отредактировано автором: 17 Февраля, 2011 - 21:17:59)

 
 Top
grefon
Отправлено: 17 Февраля, 2011 - 21:22:27
Post Id



Частый посетитель


Покинул форум
Сообщений всего: 823
Дата рег-ции: Нояб. 2010  


Помог: 32 раз(а)




Ок, а так?
PHP:
скопировать код в буфер обмена
  1. echo ceil(28);
  2. $a=floatval( 0.281*100 );
  3. echo '<br />'.ceil($a);


-----
____________________________________________________________________
Ну как то так, наверное.
http://grefon[dot]com
 
 Top
OrmaJever Модератор
Отправлено: 17 Февраля, 2011 - 21:33:51
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




Скорее всего что тип числа float вот оно и округляет. Если число целое оно должно быть int.
PHP:
скопировать код в буфер обмена
  1. $a=0.28*100;
  2. echo ceil((float)$a), '<br />';
  3. echo ceil((int)$a);

(Отредактировано автором: 17 Февраля, 2011 - 21:34:58)



-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
dessor
Отправлено: 17 Февраля, 2011 - 21:50:23
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Февр. 2011  


Помог: 0 раз(а)




grefon, так функция ошибается...
OrmaJever, подход понятен, но для других то чисел все нормально! Я могу в своем скрипте сделать исключение для этого "28", но кто может утверждать, что оно одно такое?... никто Недовольство, огорчение
К тому же по мануалу функция ceil принимает тип float...

Ну хорошо, подскажите тогда, плиз, как реализовать округление числа до двух знаков после запятой другим способом?

(Отредактировано автором: 17 Февраля, 2011 - 22:20:01)

 
 Top
OrmaJever Модератор
Отправлено: 17 Февраля, 2011 - 22:41:34
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




dessor пишет:
К тому же по мануалу функция ceil принимает тип float...

Ну вот поэтому она и округляет. Просто функция не ращитана на холостую работу (т.к. в 28 округлять нечего)
нужно поставить условие перед округлением и округлять только числа float is_float()

(Отредактировано автором: 17 Февраля, 2011 - 22:42:16)



-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
JustUserR
Отправлено: 18 Февраля, 2011 - 10:55:33
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




dessor пишет:
И что можно сделать в данном конкретном скрипте?
Действительной причиной осуществления нестабильного фунционирования операции округления в большую сторону в предполагаемого PHP-приложении является обеспечения трактования локальных числовых элементов в виде значений с плавающей точкой типа float - использование указанного метода трактования осуществляет формирование внутреннего представления числа с предварительной детерминированной погрешностью - обусловленность которой обеспечивается различием в конкретном значении десятичного числа и наиболее точным приближением комбинации элементов двоичной мантиссы и характеристического поля - таким образом для каждого из целых десятичных чисел типа N определенных в уровне float-трактования в действительности обеспечивается представление в виде N-eps или N+eps соответственно в зависимости исключительно от конкретного выбранного числа - что и осуществление выбор результата функционирования ceil-операции с недетерминированным исходом
dessor пишет:
Как в таких случаях выкручиваются профессионалы?
В качестве реального унифицированного метода решения предполагаемой задачи является использование десятичной арифметики - то есть осуществление операций с непосредственными десятичными тетрадами в десятично-двоичном коде


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
dessor
Отправлено: 18 Февраля, 2011 - 11:26:32
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Февр. 2011  


Помог: 0 раз(а)




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.

(Отредактировано автором: 18 Февраля, 2011 - 11:41:50)

 
 Top
JustUserR
Отправлено: 18 Февраля, 2011 - 11:44:07
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




dessor пишет:
Т.е. говоря простым языком, представлять числа в виде массива, как в модулях операций со сверхбольшими числами? Жесть
Осуществление решения предполагаемой задачи на основе указанной метода в действительности требует высоких вычислительных ресурсов по причине требования выполнения ассоциированных команд процессора на уровня трактования исполняемого медленного приложения - однако реальной причиной возникнования указанного аспекта функционирования является некорректное использование типа данных float для хранения чисел с фиксированной точкой
dessor пишет:
Такие глюки только с float? С int все нормально?
Проявление рассматриваемых аспектов функционирования PHP-приложения в действительности осуществляется исключительно при использовании информационных полей расположенных в уровня трактования чисел с плавающей запятой типа float или double - дело в том что в случае применение целых чисел или элементов с фиксированной точкой целевое представление является либо фиксированным либо включает односторонную детерминированную поразрядную погрешность


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
dessor
Отправлено: 18 Февраля, 2011 - 19:36:43
Post Id


Новичок


Покинул форум
Сообщений всего: 9
Дата рег-ции: Февр. 2011  


Помог: 0 раз(а)




JustUserR пишет:
однако реальной причиной возникнования указанного аспекта функционирования является некорректное использование типа данных float для хранения чисел с фиксированной точкой

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

Т.е., в int таких приколов быть неможет, правильно понял?

(Отредактировано автором: 18 Февраля, 2011 - 19:37:54)

 
 Top
Champion Супермодератор
Отправлено: 18 Февраля, 2011 - 19:50:15
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




dessor пишет:
Т.е., в int таких приколов быть неможет, правильно понял?
Да, int будет правильно округляться до ближайшего большего целого)
dessor пишет:
До такого уровня понимания php мне очень далеко)
На самом деле, это уровень понимания того, как хранятся данные вещественных типов с плавающей точкой в компутере вообще. В любом языке программирования.
 
 Top
JustUserR
Отправлено: 19 Февраля, 2011 - 20:43:08
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




dessor пишет:
А в чем заключается некорректность? И как правильно на данном примере использовать тип float? В идеале, с примером кода
Использования информационных полей типа чисел с плавающей точкой осуществляет возможность хранения нецелых величин в условием обеспечения их хранения в виде максимального ближайшего приблежения в заданном контейнерком блоке - таким образом осуществление применение операции приведения числа типа float в целому элементу может производиться исключительно на основании анализа минимального отклонения - в то время как обеспечение корректного результата для функций типа floor/ceil не может гарантироваться
dessor пишет:
Т.е., в int таких приколов быть неможет, правильно понял?
Использование информационных полей типа int для хранения целых чисел и элементов с фиксированной точкой позволяет обеспечить формирование элемента с заданной точностью - таким образом осуществление последующего использование операции преобразования в целому числу обеспечивает получение гарантированного результата
В качестве конкретного примера позволяющего пояснить указанный аспект функционирования - возможно применение того факта что при использовании целочисленных величин производится безусловное размещение оригинального элемента в разрядной сетки - в то время как использование float-информационных полей предполагает осуществление поиска соответствующего элемента с минимальной погрешностью - расположение которого может произволиться как в области больших так и меньших чисел с равной вероятностью


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Программирование на PHP »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB