![]() |
Модераторы: skyboy, MoLeX, Aliance, ksnk |
![]() ![]() ![]() |
|
capitan |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 602 Регистрация: 27.2.2005 Где: Москва Репутация: 9 Всего: 13 |
Собственно возник такой вопрос в одном из топиков. Дабы не засорять его, выношу обсуждение сюда.
Я в своих проекта всегда использую (float) исхожу из того что:
Дает такие результаты: 2147483647 12345678910 В нагруженных проектах есть поле id, которое auto_increment. Есть вероятность, что когда-то мы поймаем такую багу с intval($num) Кто что скажет? |
|||
|
||||
NNaarreekk |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 768 Регистрация: 23.6.2007 Где: Армения Репутация: 0 Всего: 3 |
capitan, ну ты и оптимист
![]() Пока на сайте дойдет до миллиарда записей, то уже наверно в место РНР еще что-нибудь придумают))) А вообще если есть конкретно ошибка при интвал значит его не нужно использовать в этом случае, ИМХО. |
|||
|
||||
Kevin |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 32 Регистрация: 20.11.2005 Репутация: 2 Всего: 2 |
Вероятность есть, а в PHP единственный тип данных для больших чисел — float.
|
|||
|
||||
Ипатьев |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2232 Регистрация: 5.7.2009 Репутация: 28 Всего: 37 |
может быть, кто-нибудь здесь осилит раздел документации, посвященный типам данных?
|
|||
|
||||
sTa1kEr |
|
|||
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
Это не бага. http://php.net/int Это сообщение отредактировал(а) sTa1kEr - 3.11.2009, 14:23 |
|||
|
||||
Simpliest |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 625 Регистрация: 1.9.2009 Репутация: 1 Всего: 3 |
А зачем? ![]() И типам данных чего? MySQL? PHP? В теории 2млрд записей хватит на 68 лет при скорости 1 запись в секунду ![]() Если мы увеличим скорость до 100к в секунду, то всего около 6 часов. Другой вопрос, что тогда автоинкрементный id скорее всего будет несколько неактуален ![]() С флоатом тоже не все так гладко ![]() ![]() Ну и на закуску.... В теории при переходе на полностью 64 битные системы ваше целое число вырастет ![]() ![]() Поправка ![]() Это сообщение отредактировал(а) Simpliest - 3.11.2009, 14:30 |
|||
|
||||
youri |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 17.4.2004 Репутация: 6 Всего: 16 |
при использовании prepared statements (mysqli) intval/float не нужны, т.е. id всегда будет храниться в виде строки. Да и для mysql не обязательно, можно просто проверять, что id (пришедший от пользователя) содержит только цифры
|
|||
|
||||
sTa1kEr |
|
|||
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
||||
|
||||
youri |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 17.4.2004 Репутация: 6 Всего: 16 |
кстати, кто-нибудь знает, до каких пор можно рассчитывать, что "целочисленная" строка преобразуется в float без потерь? Я так понимаю до 2**52-1?
|
|||
|
||||
Kevin |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 32 Регистрация: 20.11.2005 Репутация: 2 Всего: 2 |
Не напомните, что совершенно случайно передается первым аргументом в bind_param()? ![]() -- Про БД конечно не совсем это актуально, но, как я понял, топикстартер просто привел неудачный пример, иллюстрируя несколько другую идею. Это сообщение отредактировал(а) Kevin - 3.11.2009, 15:08 |
|||
|
||||
Simpliest |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 625 Регистрация: 1.9.2009 Репутация: 1 Всего: 3 |
Я же ответил Плясать лучше отсюда http://www.psc.edu/general/software/packages/ieee/ieee.php 2 цифры уйдут на округление. Добавлено через 1 минуту и 7 секунд Kevin, для очень больших чисел всегда есть GMP и BCMath 100 знаков точности - не предел. |
|||
|
||||
Kevin |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 32 Регистрация: 20.11.2005 Репутация: 2 Всего: 2 |
К самому PHP они относятся слабо, и не отменяют того, что есть только int и float. А тот же BCMath, в конечном счете, отдает простую строку. P.S.: Вообще, о чем спор? Есть int, есть float, есть разные уловки и библиотеки как преодолеть ограничения, о чем топик? |
|||
|
||||
capitan |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 602 Регистрация: 27.2.2005 Где: Москва Репутация: 9 Всего: 13 |
Сразу скажу, я не теоретик, а практик. Просто зашел спор как приводить полученную переменную. Я привожу всегда (float), Ипатьев говорит что нужно использовать intval. Я привел пример, может и не удачный, но исходя из чего я исходил. Можно было конечно привести пример online калькулятора. Вот хочу понять, когда применять intval, а когда float. |
|||
|
||||
bars80080 |
|
|||
![]() прапор творюет ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Завсегдатай Сообщений: 12022 Регистрация: 5.12.2007 Где: Königsberg Репутация: 71 Всего: 315 |
для случаев где проверяется число менее 11 знаков - intval, для случаев большего -
100%-вариант |
|||
|
||||
Ипатьев |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2232 Регистрация: 5.7.2009 Репутация: 28 Всего: 37 |
Насколько я помню, с вещественными числами могут быть проблемы.
Когда 1111111111 станет вдруг 1111111110.99999999 Сейчас, правда, воспроизвести их не удалось. Но, на мой взгляд, функцию надо применять по назначению. Если нам нужно целое - мы приводим к целому. Если нужно вещественное - приводим к вещественному. Не наоборот. |
|||
|
||||
sTa1kEr |
|
|||
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
capitan, для целых чисел нужно использовать intval, для вещественных floatval, но никак не иначе. При работе с большими целыми числами на 32х существуют соответствующие экстеншены приведенные выше. Для проверки является ли строка числом есть функция http://php.net/is_numeric
|
|||
|
||||
Simpliest |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 625 Регистрация: 1.9.2009 Репутация: 1 Всего: 3 |
capitan, можешь применять и регулярку. Тогда смело забьешь на число значащих цифр.
Вопрос в том, что в твоих стандартных проектах ты не упрешься даже в лимит int. |
|||
|
||||
bars80080 |
|
|||
![]() прапор творюет ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Завсегдатай Сообщений: 12022 Регистрация: 5.12.2007 Где: Königsberg Репутация: 71 Всего: 315 |
100%-вариант. получим 1, ибо id стандартно - unsigned Добавлено через 2 минуты и 2 секунды
я упёрся. и не потому, что у меня такая большая база, а потому что у других большая база. платёжная система сбрасывает свои данные под уникальным идентификатором, который я пишу к себе в базу. а у них там уже под 20 знаков |
|||
|
||||
Simpliest |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 625 Регистрация: 1.9.2009 Репутация: 1 Всего: 3 |
А он у них не цифровой. Там что хоть 65000 знаков. |
|||
|
||||
bars80080 |
|
|||
![]() прапор творюет ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Завсегдатай Сообщений: 12022 Регистрация: 5.12.2007 Где: Königsberg Репутация: 71 Всего: 315 |
||||
|
||||
Simpliest |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 625 Регистрация: 1.9.2009 Репутация: 1 Всего: 3 |
bars80080,
Я некорректно выразился, но все равно верь мне ![]() ![]() Счета, номера карт - не являются числами. Да, они обычно состоят из одних цифр - но это строки. И исключительно строки. Добавлено через 1 минуту и 5 секунд GUID, ID транзакции - тоже не числа. |
|||
|
||||
bars80080 |
|
|||
![]() прапор творюет ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Завсегдатай Сообщений: 12022 Регистрация: 5.12.2007 Где: Königsberg Репутация: 71 Всего: 315 |
а я не работал в банке, но данные о проведённых платежах приходят в виде чисел. особо говорено, что id платежа - уникальный идентификатор состоящий исключительно из цифр. какая мне разница, как и где оно у них там хранится? я ставлю себе bigint и в ус не дую Simpliest, вот серьёзно, насколько вы лучше меня можете знать приходящий мне формат данных, если я даже не указал о какой системе веду речь? |
|||
|
||||
sTa1kEr |
|
|||
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
В каком, простите, месте это стандартно? Но в любом случае - это не корректный способ проверки числа.
В PHP любые данные из-вне поступают в виде строк. Это сообщение отредактировал(а) sTa1kEr - 3.11.2009, 20:04 |
|||
|
||||
solenko |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1473 Регистрация: 15.1.2006 Где: Украина Репутация: 34 Всего: 67 |
Почему? Почему не (int) и (float) соответственно? -------------------- Ла-ла-ла-ла Заметьте, нет официального подтверждения, что это не просто четыре слога. |
|||
|
||||
youri |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 17.4.2004 Репутация: 6 Всего: 16 |
так это не способ проверки числа вообще, это способ использования переданного id. Только запихнуть нужно куда-нибудь эти манипуляции, в функцию/класс думаю, "стандартно" нужно понимать как "обычно". В mysql primary key + auto_increment не может создать отрицательный id. А что бывает необходимость в отрицательных id? |
|||
|
||||
sTa1kEr |
|
||||
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
Само собой разумеется, что можно использовать (int) и (float). Я лишь имел ввиду то-же самое, что за минуту до меня сказал Ипатьев. Добавлено через 10 минут и 13 секунд
Да, прошу прощенья, изначально речь шла исключительно об ID. Но суть моего сообщения была в том, что таким способом можно получить заведомо не правильный ID, а это в свою очередь может привести к плачевным последствиям.
С таким же успехом можно сказать, что стандартно ID - это строка из 36 символов, т.к. обычно в MSSQL primaty key - это GUID. Да, бывает потребность в совершенно разных ID. |
||||
|
|||||
Simpliest |
|
||||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 625 Регистрация: 1.9.2009 Репутация: 1 Всего: 3 |
Я же сказал уже И поправился
И плохо. Потому что это 64-битное целое и таким образом ты можешь хранить только 18ти-значные вещи (19я цифра может быть единицей) состоящие исключительно из цифр. Например, у нас счет 14ти-символьный. А у вас в России он уже может быть 20ти-символьным (он дейтствительно 20тизначный, но некоторые банки сокращают внутренний счет на несколько цифр) Номера карт распространенных МПС - 16 символов. Но есть варианты и с 20тью и даже алфавитно-цифровые Чтобы понять что счет это не число - можешь прочитать хотя бы его определение у вас Рассчетный счет
Речь идет о том, что UID,ID, GUID, счета, номера карточек, серийные номера и т.д. и т.п. - не являются числами хотя и могут состоять исключительно из цифр. Поэтому хранить ты можешь как угодно, но не забывать чем они являются на самом деле. В случае с MySQL вас всех вводит в заблуждение автоинкрементное целочисленное поле в качестве sequence. В более взрослых базах это может быть вообще не число (Oracle, Interbase/Firebird, DB2) |
||||||
|
|||||||
bars80080 |
|
||||||||||
![]() прапор творюет ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Завсегдатай Сообщений: 12022 Регистрация: 5.12.2007 Где: Königsberg Репутация: 71 Всего: 315 |
у вас id бывают отрицательные? ну, это уже зависит от задачи. я думал, что речь идёт от прошлой темы, где проверялся идентификатор. там цель была не в числе, а именно в корректном идентификаторе. ![]()
![]()
не понял. каким образом из этого:
может получиться не корректный id? я сейчас посмотрел, они у меня 15-значные
читать не буду, повторюсь только третий раз: я говорю не о счетах, а об идентификаторах операций. это не сертифицированная каким-то ведомством величина, это всего лишь порядковый номер принятый внутри организации для сохранения единого реестра. да они могли сделать его буквенным, но они сами себе прописали формат, что он - число. и опубликовали формат для всех партнёров, чтобы мы могли с ними сотрудничать. всё
легко может быть. я отдаю этой же системе свои идентификаторы в виде БЦБЦЦЦЦ-ЦЦ, потому что мне так удобно, и это вписывается в их формат данных но это специфичный формат, и я его парсю соответствующим образом, вытаскивая из него систему оборота, идентификатор заказа и номер операции по ней но мы говорим о частной ситуации, вытащенной из другой темы. и я её в очередной раз решаю инженерным способом, т.е. частно. что, видимо, не приветствуется в программерской среде. почему-то вам всегда нужны универсальные алгоритмы. вот скажи, можно ли придумать универсальный метод проверки на корректность для входящего идентификатора - состоящего из одних цифр и для идентификатора - БЦБЦЦЦЦ-ЦЦ? |
||||||||||
|
|||||||||||
Nigel |
|
|||
познаю мир ![]() ![]() Профиль Группа: Участник Сообщений: 515 Регистрация: 20.11.2007 Репутация: 7 Всего: 19 |
Собственно, зачем используется такая конструкция (int)$value? Посмотрите 1-й пост, ТС использует этот как фильтр
в своих запросах. А нужно ли это? Все нормальные либы используют биндинг для добавления переменных в запрос. Многие утверждают, что данные должны поступать в бд в неизменном виде, сами при этом нарушая свой принцип подобными конструкциями. ТС аргументировал такое поведение нагруженными проектами. Интересно узнать, какие проекты он считает нагруженными?;) На нормальные сервера ставят 64бита, и не изза того, что вы можете выйти за диапазон значений, а просто тупо потому, чтобы обеспечить нормальную работу с большими объемами памяти. В этом случае никаких проблем начальная конструкция не вызовет. А вот используя float, проблемы как раз получить можно. Это и точка(запятая), связанная с локализацией, и представление числа в виде строки, и выполнение арифметических операций, в результате чего будете получать совсем не то, что ожидаете. К тому же есть люди, которые используют везде (float), а при этом тип столбца у них в БД какой-нить smallint. А еще забавно, когда пишут абстрактный слой для бд, при этом сами запросы в никакой другой бд работать не будут, кроме mysql. Ради чего усилия тогда, спрашивается? Кто-то говорит "Я везде использую bigint. Я от всего застрахован". Может тогда для строк заюзать везде longtext? Чем больше диапазон, тем больше требуется памяти для хранения. А нужно ли это? Может быть, не стоит создавать дополнительных проблем? Может быть, все на самом деле проще... |
|||
|
||||
youri |
|
||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 17.4.2004 Репутация: 6 Всего: 16 |
я считаю, что bars80080 выбрал неподходящее слово. Более подходящее слово - обычно
не забывая про диапазон значений в этих строках
holy war detected! |
||||||||
|
|||||||||
Simpliest |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 625 Регистрация: 1.9.2009 Репутация: 1 Всего: 3 |
Решай наздоровье. Это правильно и разумно. А когда для борьбы с сферическими багами intval начинают использовать float, не учитывая при этом с чем работают - это не правильно. Придумать можно что угодно. Но это не нужно ![]() (int)$id - вполне разумное применение, когда у тебя ID - это INT в MySQL и в топку всякие float Когда у тебя ID это BIGINT и 32-битная система, то твоя регулярка вполне подходящее решение. Делать везде BIGINT вместо INT - это не совсем разумно. С чем ты пытаешься спорить? ![]() |
|||
|
||||
bars80080 |
|
|||
![]() прапор творюет ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Завсегдатай Сообщений: 12022 Регистрация: 5.12.2007 Где: Königsberg Репутация: 71 Всего: 315 |
да вроде не я пытаюсь спорить я сказал, что для заявленного случая (когда id числовое, что верно в большинстве случаев) регуляркой снимаются все ограничения на intval и не допускаются подобные ляпсусы как -5 или 0х55 от is_numeric и иже с ним. мне тут заявили, что это не 100% вариант (если речь велась, что не 100%, потому что id бывает и буквенный, то согласен. как-то не втыкнулся сразу) |
|||
|
||||
youri |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 17.4.2004 Репутация: 6 Всего: 16 |
а какая разница, что прокатит -5 или 0х55? Это ж в основном защита от SQL Injection, или я не прав? Или есть другие причины превращать id в число? |
|||
|
||||
bars80080 |
|
|||
![]() прапор творюет ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Завсегдатай Сообщений: 12022 Регистрация: 5.12.2007 Где: Königsberg Репутация: 71 Всего: 315 |
ну, тут уж я особо не размышлял, предпочитаю иметь в руках что-то конкретное допустим такая ситуация: попадается мне 0х4, ищу в базе where id=0x4 , при наличии id=4, что он вернёт? |
|||
|
||||
sTa1kEr |
|
|||
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
Да, бывают. Пример каким образом можно получить не корректный ID, а в последствии логическую ошибку, я указал выше. И если вам так нравятся пользоваться кривыми велосипедами, вместо проверенный штатных задокументированных способов, то пожалуйста, это ваше дело. Главное не подавать плохие примеры другим пользователям.
А вы сами как думаете? Затем, что в PHP нету типизации переменных, по этому, что бы быть уверенным, что в переменной находится int необходимы подобные конструкции. |
|||
|
||||
bars80080 |
|
|||
![]() прапор творюет ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Завсегдатай Сообщений: 12022 Регистрация: 5.12.2007 Где: Königsberg Репутация: 71 Всего: 315 |
даже не знаю, что сказать. прошу прощения заранее, но неужели отрицательный id - это хороший пример? так, у меня сейчас появился пхп и я проверил. мда, в целом при сохранении формата в дальнейшем он работает как часы. то есть на where id=0x26, он выдаст строку с id=38, и если вставить строку с тем же 0x26, то она станет id=38 но это всё при условии, что нигде число не будет порубано на предмет вредных символов |
|||
|
||||
Nigel |
|
|||
познаю мир ![]() ![]() Профиль Группа: Участник Сообщений: 515 Регистрация: 20.11.2007 Репутация: 7 Всего: 19 |
sTa1kEr, ты так ничего и не понял из того, что я выше написал. Для защиты от sql-inj это вовсе не обязательно. |
|||
|
||||
sTa1kEr |
|
||||||
9/10 программиста ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1553 Регистрация: 21.2.2007 Репутация: 56 Всего: 146 |
С учетом того, что в PHP нету ни long'ов, ни unsigned integer, иногда приходится так поступать. А иногда приходится работать с данными из внешних источников, использующих такие ID.
Именно ![]() Добавлено через 4 минуты и 21 секунду
Я ни слова не сказал про sql инъекции. Я говорил про типы переменных, не смотря на то, что в PHP нету строгой типизации, он все же, разумеется, различает типы переменных. И единственный корректный способ привести строку к типу integer - это использовать intval (или аналоги в вроде (integer), (int) ). |
||||||
|
|||||||
youri |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 740 Регистрация: 17.4.2004 Репутация: 6 Всего: 16 |
Nigel пришел к нам со знанием какие либы есть "нормальные" (: Кстати, то, что ты говорил, прозвучало в самом начале |
|||
|
||||
Nigel |
|
|||
познаю мир ![]() ![]() Профиль Группа: Участник Сообщений: 515 Регистрация: 20.11.2007 Репутация: 7 Всего: 19 |
Я вкурсе про типы данных в php. Перечитай первый пост топика. |
|||
|
||||
![]() ![]() ![]() |
Правила форума "PHP" | |
|
Новичкам:
Важно:
Внимание:
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | PHP: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |