Почему сумма двух MaxIntegers возвращает -2? [Дубликат]

Некоторые достойные ответы, но просто подумал, что я немного расширю, чтобы объяснить более четко, когда PHP определяет, является ли массив пустым.


Основные примечания:

Массив с ключом (или ключами) будет определен как NOT empty с помощью PHP.

Поскольку значениям массива нужны ключи для существования, значения или нет в массиве не определяют, является ли он пустым, только если ключей нет (и, следовательно, нет значений).

Таким образом, проверка массива с empty() не просто говорит вам, есть ли у вас значения или нет, это говорит вам, что массив пуст, а ключи являются частью массива.


Итак, рассмотрите, как вы создаете массив, прежде чем принимать решение о том, какой метод проверки использовать. EG В массиве есть ключи , когда пользователь отправляет вашу форму HTML, когда каждое поле формы имеет имя массива (т.е. name="array[]"). Массив non empty будет создан для каждого поля, так как для каждого массива поля формы будут добавлены значения с автоматическим увеличением.

Возьмите эти массивы, например:

/* Assigning some arrays */

// Array with user defined key and value
$ArrayOne = array("UserKeyA" => "UserValueA", "UserKeyB" => "UserValueB");

// Array with auto increment key and user defined value
// as a form field would return with user input
$ArrayTwo[] = "UserValue01";
$ArrayTwo[] = "UserValue02";

// Array with auto incremented key and no value
// as a form field would return without user input
$ArrayThree[] = '';
$ArrayThree[] = '';

Если вы выделите ключи массива и значения для указанных выше массивов, вы получите следующее:

ARRAY ONE: [UserKeyA] => [UserValueA] [UserKeyB] => [UserValueB]

ARRAY TWO: [0] => [UserValue01] [1] => [UserValue02]

ARRAY THREE: [0] => [] [1] => []

И тестирование вышеуказанных массивов с помощью empty() возвращает следующие результаты:

ARRAY ONE: $ ArrayOne не пуст

ARRAY TWO: $ ArrayTwo не пуст

ARRAY THREE: $ ArrayThree не пуст

Массив всегда будет пустым, когда вы назначаете массив, но не используете его после этого, например:

$ArrayFour = array();

Это будет пустым, то есть PHP вернет TRUE при использовании if empty() выше.

Итак, если ваш массив имеет ключи - либо, например, имена ввода формы, либо если вы назначили их вручную (т. е. создать массив с именами столбцов базы данных в качестве ключей, но не иметь значений / данных из базы данных), тогда массив НЕ будет empty().

В этом случае вы можете закодировать массив в foreach, тестируя, имеет ли каждый ключ значение. Это хороший метод, если вам все равно нужно проходить через массив, возможно, проверять ключи или дезинфицировать данные.

Однако это не лучший метод, если вам просто нужно знать, «если существуют значения», возвращает TRUE или FALSE . Существуют различные методы, чтобы определить, имеет ли массив какие-либо значения, когда он знает, что у него будут ключи. Функцией или классом может быть лучший подход, но, как всегда, это зависит от вашей среды и точных требований, а также от других вещей, таких как то, что вы сейчас делаете с массивом (если есть).


Вот подход, который использует очень маленький код для проверки того, имеет ли массив значения:

Использование array_filter(): Итерирует по каждому значению в массиве, передавая их функции обратного вызова. Если функция обратного вызова возвращает значение true, текущее значение из массива возвращается в массив результатов.

$EmptyTestArray = array_filter($ArrayOne);

if (!empty($EmptyTestArray))
  {
    // do some tests on the values in $ArrayOne
  }
else
  {
    // Likely not to need an else, 
    // but could return message to user "you entered nothing" etc etc
  }

Выполнение array_filter() во всех трех примерах массивов (созданных в первом блоке кода в этом ответе) приводит к следующему:

ARRAY ONE: $ arrayone не пуст

ARRAY TWO: $ arraytwo не пуст

ARRAY THREE: $ arraythree empty

Итак, когда нет значений, есть ли ключи или нет, используя array_filter() для создания нового массива, а затем проверьте, пуст ли новый массив, показывает, были ли какие-либо значения в исходном массиве. Это не идеально и немного беспорядочно, но если у вас огромный массив и не нужно его прокручивать по какой-либо другой причине, то это самый простой с точки зрения кода.


У меня нет опыта проверки накладных расходов, но было бы полезно узнать различия между использованием array_filter() и foreach проверки, найдено ли значение.

Очевидно, что эталонный показатель должен быть по разным параметрам, на малых и больших массивах и когда есть значения и т. Д.

15
задан Earlz 15 April 2010 в 00:09
поделиться

9 ответов

Целочисленное переполнение происходит, когда вы пытаетесь выразить число, которое больше, чем наибольшее число, которое может обрабатывать целочисленный тип.

Если вы попытаетесь выразить число 300 в одном байте, у вас будет целочисленное переполнение (максимум 255). 100 000 в двух байтах также является переполнением целых чисел (65535 - это максимум).

Вам нужно заботиться об этом, потому что математические операции не будут вести себя так, как вы ожидаете. A + B фактически не равен сумме A и B, если у вас есть переполнение целых чисел.

Вы избегаете этого, не создавая условие в первую очередь (обычно либо путем выбора типа целого типа достаточно большой, чтобы вы не переполняли или не ограничивали ввод пользователя, чтобы переполнение не происходило).

18
ответ дан John 20 August 2018 в 18:07
поделиться

Это происходит, когда вы пытаетесь использовать целое число для значения, которое больше, чем внутренняя структура целого может поддерживать из-за количества используемых байтов. Например, если максимальный целочисленный размер равен 2,147,483,647, и вы пытаетесь сохранить 3 000 000 000, вы получите ошибку переполнения целых чисел.

-1
ответ дан CS. 20 August 2018 в 18:07
поделиться
  • 1
    Переполнение является артефактом математических операций, а не назначением / хранением. – dthorpe 14 April 2010 в 22:53

Из wikipedia :

В компьютерном программировании происходит переполнение целых чисел, когда арифметическая операция пытается создать числовое значение, которое больше, чем может быть представлено в пределах доступное пространство для хранения. Например, добавление 1 к наибольшему значению, которое может быть представлено, представляет собой целочисленное переполнение. Наиболее общий результат в этих случаях заключается в том, что наименее значимые представляемые биты результата должны быть сохранены (результат считается завершенным).

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

0
ответ дан Darin Dimitrov 20 August 2018 в 18:07
поделиться
  • 1
    это отвечает на то, что, но не на то, почему и как – David 14 April 2010 в 22:50

Переполнение происходит, когда результат арифметической операции не соответствует типу данных операции. У вас может быть переполнение с байтом без знака, если вы добавите 255 + 1, потому что результат (256) не вписывается в 8 бит байта.

У вас может быть переполнение с плавающей запятой номер, если результат операции с плавающей запятой слишком велик для представления в показателе типа данных с плавающей запятой или мантиссы.

Вы также можете иметь underflow с типами с плавающей запятой, когда результат операции с плавающей запятой слишком small для представления в заданном типе данных с плавающей запятой. Например, если тип данных с плавающей запятой может обрабатывать показатели в диапазоне от -100 до +100, и вы присваиваете значение с показателем -80, результат будет иметь показатель около -160, который не будет соответствовать данный тип данных с плавающей запятой.

Вы должны быть обеспокоены переполнениями и недоисполнениями в вашем коде, потому что это может быть тихий убийца: ваш код производит неправильные результаты, но может не сигнализировать об ошибке.

Независимо от того, можете ли вы спокойно игнорировать переполнения, очень многое зависит от характера вашей программы - отображать пиксели экрана из 3D-данных гораздо больший допуск для числовых ошибок, чем, скажем, финансовые расчеты.

Проверка переполнения часто отключается в настройках компилятора по умолчанию. Зачем? Поскольку дополнительный код для проверки переполнения после каждой операции требует времени и пространства, что может ухудшить производительность вашего кода во время выполнения.

Сделайте себе одолжение и, по крайней мере, разработайте и протестируйте свой код с проверкой переполнения.

1
ответ дан dthorpe 20 August 2018 в 18:07
поделиться

Самый простой способ объяснить это с помощью тривиального примера. Представьте, что у нас есть 4-битное целое число без знака. 0 будет 0000, а 1111 - 15. Поэтому, если вы увеличиваете 15 вместо 16, вы обмениваетесь назад до 0000, так как 16 на самом деле 10000, и мы не можем представить это с менее чем 5 бит. Переполнение Ergo ...

На практике числа намного больше и округляются до большого отрицательного числа при переполнении, если int подписан, но в основном это происходит.

Другое способ взглянуть на это - считать это в значительной степени тем же самым, что случается, когда одометр в вашем автомобиле снова обрушивается на ноль после удара 999999 км / миль.

7
ответ дан Felipe Warrener-Iglesias 20 August 2018 в 18:07
поделиться

Я бы хотел быть немного противоположным ко всем остальным ответам, которые каким-то образом принимают дрянную сломанную математику как данность. Вопрос помечен как языковой-агностик, а на огромном количестве языков целые числа просто никогда не переполняются, поэтому вот мой вид саркастического ответа:

Что такое ошибка переполнения целого числа?

Устаревший артефакт из темных эпох вычислений.

почему мне это нужно?

У вас нет.

как его можно избежать?

Использовать современный язык программирования, в котором целые числа не переполняются. (Lisp, Scheme, Smalltalk, Self, Ruby, Newspeak, Ioke, Haskell, возьмите свой выбор ...)

1
ответ дан Jörg W Mittag 20 August 2018 в 18:07
поделиться

Из http://www.first.org/conference/2006/papers/seacord-robert-slides.pdf :

Целочисленное переполнение происходит, когда целое число увеличивается за пределы его максимального значения или уменьшается ниже его минимального значения. Переполнение может быть подписано или без знака.

PS: В PDF есть подробное объяснение переполнения и других целочисленных условий ошибки, а также способы их устранения / исключения.

0
ответ дан N 1.1 20 August 2018 в 18:07
поделиться

Когда вы храните целое число в памяти, компьютер сохраняет его в виде серии байтов. Они могут быть представлены как серия единиц и нулей.

Например, нуль будет представлен как 00000000 (8-битные целые числа), и часто 127 будут представлены как 01111111. Если вы добавите один из 127, это «перевернит» биты и заменит его на 10000000, но в представлении комплимента в стандарте , это фактически используется для представления -128. Это «переполняет» значение.

С неподписанными номерами происходит то же самое: 255 (11111111) плюс 1 станет 100000000, но так как есть только 8 "бит", это заканчивается как 00000000, который равен 0.

Вы можете избежать этого, выполнив правильную проверку диапазона для вашего правильного целочисленного размера или используя язык, который делает правильную обработку исключений для вас.

2
ответ дан Reed Copsey 20 August 2018 в 18:07
поделиться
  • 1
    10000000 - INT_MIN (например, -128 для 1 подписанного байта) в дополнении 2. -1 - FFFFFFFF. – indiv 14 April 2010 в 23:19

Ошибка целочисленного переполнения возникает, когда операция делает целочисленное значение больше его максимального значения.

Например, если максимальное значение, которое вы можете иметь, равно 100000, а ваше текущее значение равно 99999, затем добавление 2 сделает это «переполнением».

Вы должны заботиться о переполнении целых чисел, поскольку данные могут быть изменены или потеряны непреднамеренно и могут избежать их либо с большим целым типом (см. long int на большинстве языков), либо с помощью схема, которая преобразует длинные строки цифр в очень большие целые числа.

1
ответ дан Riddari 20 August 2018 в 18:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: