Прихващане на изключение от целочислено препълване във FreePascal

Опитвам се с тази проста програма да хване изключения.

Изключението делене на нула е успешно уловено. Изглежда обаче не мога да уловя препълването на целите числа.

Разбирам, че цяло число от тип SmallInt ще препълни след +32767, тъй като най-голямата стойност със знак = 2^15 - 1 (т.е. +32767).

Ето кода:

Program ss;

Var

  Price, Qty: SmallInt;
  Rate: Real;

Begin
  Try

    write('Enter Total price '); Readln(Price);
    Write('Enter qty '); Readln(Qty);

    Rate := Price / Qty;
    Writeln('Single item = ', Rate:0:2);

  except
    On EDivByZero Do Writeln('qty must be a valid num above 0');
    On EIntOverflow Do Writeln('too large')
  end;
End.

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

Ето изхода:

Въведете обща цена 32768

Въведете кол. 1

Единичен артикул = -32768.00

Натиснете произволен клавиш, за да се върнете към IDE

Правя ли нещо грешно в кода? Какъв е правилният метод за улавяне на целочисленото препълване във FreePascal?

Благодаря!


person itsols    schedule 07.01.2016    source източник
comment
Не съм експерт по Free Pascal, но предполагам, че изключението за препълване се задейства само в резултат на изчисление. Разделянето на 1 не променя стойността, така че не генерира изключение. Опитайте да добавите, извадите или умножите стойности, които са в диапазона, но резултатът от операцията е извън диапазона. Например x := 32767; x := x+1   -  person Stuart    schedule 07.01.2016
comment
@Stuart Благодаря за вашия принос. Опитах се да умножа 17000 по 2 и да го съхраня в SmallInt. Даде изход като -31536. Така че, с други думи, той препълва, но не попада в кода за обработка на изключения.   -  person itsols    schedule 07.01.2016
comment
Защо не опитате кода, който предложих. 17000 * 2 вероятно ще се изпълни като цяло числово умножение и когато съхраните резултата в smallint, той след това се съкращава до smallint. Съкращаването на цяло число не е изчисление и така може да не генерира изключение за препълване на цяло число.   -  person Stuart    schedule 07.01.2016
comment
@Stuart За вашия пример изходът е -32768 (което е препълващата стойност) и не се задейства изключение. Спомням си някакъв по-стар език (мисля, че беше VB6, но не мога да потвърдя това в момента), даващ подобен резултат. Благодаря отново.   -  person itsols    schedule 07.01.2016


Отговори (1)


Трябва да включите модула sysutils, тъй като той съдържа кода, който променя най-дълбокия вид грешки по време на изпълнение в уловими езикови изключения

person Marco van de Voort    schedule 07.01.2016
comment
Благодаря Марко. Освен да включа това устройство, има ли нещо, което трябва да направя? Включих го и работи без никакви промени. - person itsols; 07.01.2016
comment
Колкото и да си струва, моята версия на компилатора показва 2.6.2-8 в менюто Помощ › Относно - person itsols; 07.01.2016