Что такое арифметическое недополнение и переполнение в C?

Что означают арифметические недополнения и переполнения в программировании на C?


person Registered User    schedule 15.06.2011    source источник


Ответы (4)


Переполнение

Из http://en.wikipedia.org/wiki/Arithmetic_overflow:

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

Так, например:

uint32_t x = 1UL << 31;
x *= 2;  // Overflow!

Обратите внимание, что, как упоминает @R в комментарии ниже, стандарт C предлагает:

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

Конечно, это довольно своеобразное определение «переполнения». Большинство людей назвали бы сокращение по модулю (т. е. циклический переход) «переполнением».

Недополнение

Из http://en.wikipedia.org/wiki/Arithmetic_underflow:

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

Так, например:

float x = 1e-30;
x /= 1e20; // Underflow!
person Oliver Charlesworth    schedule 15.06.2011
comment
Ваш пример переполнения неверен на языке стандарта C. Беззнаковые типы не могут переполняться. - person R.. GitHub STOP HELPING ICE; 16.06.2011
comment
@R.: Переполнение, безусловно, имеет хорошо понятное значение, независимое от стандарта C! Но вы правы, поэтому я включу этот факт в свой ответ. - person Oliver Charlesworth; 16.06.2011
comment
Различие в основном важно, когда люди говорят, что такие вещи, как целочисленное переполнение, всегда приводят к неопределенному поведению. - person R.. GitHub STOP HELPING ICE; 16.06.2011
comment
А как насчет unsigned char x = 0; x -= 1; ? считается ли это недостатком? - person Gamal Othman; 25.02.2019
comment
Я нашел в Википедии, что это называется Integer Overflow или Integer Wraparound. В нем говорится: Обратите внимание, что сохранение слишком низких значений в целочисленной переменной (например, попытка сохранить -1 в беззнаковом целом) правильно называется целочисленным переполнением или, в более широком смысле, целочисленным переносом. Термин «потеря памяти» обычно относится только к числам с плавающей запятой и является отдельной проблемой. Спасибо! - person Gamal Othman; 25.02.2019

Компьютеры используют только 0 и 1 для представления данных, поэтому диапазон значений, которые могут быть представлены, ограничен. Многие компьютеры используют 32 бита для хранения целых чисел, поэтому наибольшее целое число без знака, которое можно сохранить в этом случае, равно 2^32 -1 = 4294967295. Но первый бит используется для представления знака, так что на самом деле наибольшее значение равно 2^31 - 1 = 2147483647.

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

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

person AlexandraC    schedule 13.01.2014

int, самый распространенный тип данных в C, является 32-битным типом данных. Это означает, что каждому int отводится 32 бита в памяти. Если бы у меня была переменная

int a = 2;

это фактически будет представлено в памяти как 32-битное двоичное число: 0000000000000000000000000000000010.

Если у вас есть два двоичных числа, например

100000000000000000000000000000000
и
100000000000000000000000000000000,

их сумма будет 1000000000000000000000000000000000, что составляет 33 бита. Однако компьютер берет только 32 младших значащих бита, все из которых равны 0. В этом случае компьютер распознает, что сумма больше, чем может быть сохранено в 32 битах, и выдает ошибку переполнения.

Нижний поток — это в основном то же самое, происходящее в противоположном направлении. Стандарт с плавающей запятой, используемый для C, допускает 23 бита после запятой; если число имеет точность выше этой точки, оно не сможет сохранить эти биты. Это приводит к ошибке потери значимости и/или потере точности.

person Ben Sutton    schedule 15.06.2011
comment
У компьютера обычно нет проверок того, что операция привела к переполнению. А откуда вы взяли 23? - person Oliver Charlesworth; 16.06.2011
comment
int не является 32-битным типом данных. - person Philip; 16.06.2011
comment
@OliCharlesworth: в соответствии с IEEE 754 число с плавающей запятой одинарной точности имеет 23 бит (не цифру) значащую. Существует также неявный бит, который обычно дает вам 24-битную точность, но не применяется во время потери значимости, когда используются субнормальные числа для обеспечения постепенной потери точности. - person Michael Carman; 21.06.2013
comment
Ваше описание нижнего потока совершенно неверно. Числа с плавающей запятой состоят из трех полей: знака, мантиссы (дробной части) и показателя степени. Количество битов в мантиссе определяет точность (примерно 7 десятичных знаков для 32-битного числа с плавающей запятой). Количество битов в показателе степени определяет диапазон (от меньшего к большему) представляемых значений. Положение десятичной точки определяется значением показателя степени и не зависит от точности. Потеря значимости происходит, когда сохраняемое значение меньше по величине, чем минимальное значение, которое может поддерживать показатель степени. - person Michael Carman; 21.06.2013
comment
@Oli Charlesworth: обычно каждый процессор имеет флаг переполнения в своем регистре состояния. (Возможно, вы имели в виду, что C это не волнует) - person Curd; 13.01.2014
comment
@Curd: Да, я не могу вспомнить, что я имел в виду в то время! Надеюсь, я имел в виду, что вы не можете получить доступ к флагу состояния из C... - person Oliver Charlesworth; 13.01.2014
comment
определение недолива не совсем корректно. - person hamid kavianathar; 12.05.2020

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

person anita    schedule 26.10.2014
comment
вы смешиваете вещи: арифметическое недополнение с переполнением стека и соединяете их вместе, что в лучшем случае делает ваш ответ запутанным. Я тоже не уверен, что согласен с вашими определениями. - person bolov; 26.10.2014
comment
Ваш ответ говорит только о том, в чем разница между ними, но не говорит, что они; заголовок вопроса: что такое недолив и перелив - person GingerPlusPlus; 26.10.2014