Проверка на переполнение при вычислении выражения - C (СИ)
Формулировка задачи:
Доброго времени суток. Помогите пожалуйста с одним вопросом. Имеется задание: Написать программу, проверяющую ряд тождеств, часть из которых является общеизвестными арифметическими тождествами. Для этого необходимо вычислить левую и правую часть арифметического выражения. В процессе вычислений необходимо контролировать переполнение разрядной сетки. Результаты вычислений отображаются на экране.
Решить задачу необходимо на С++ и ассемблере.
Саму программу я написал, но вот как выполнить проверку на переполнение не знаю.. Вот сама программа
#include <stdio.h>
#define var 14
int main()
{
int a,b,c,a1,b1,c1,left,right,left_a,right_a;
printf("Input a, b, c for (a-b-c)^2 = a^2+b^2+c^2-2ab-2ac+2bc\n");
scanf("%i%i%i",&a,&b,&c);
a1=a/(var+2);
b1=b/(var+3);
c1=c/(var+4);
left = (a1-b1-c1)*(a1-b1-c1);
right = (a1*a1)+(b1*b1)+(c1*c1)-2*a1*b1-2*a1*c1+2*b1*c1;
__asm{
mov eax,a //a1=a/(var+2)
cdq
mov ebx,var+2
idiv ebx
mov esi,eax
mov eax,b //b1=b/(var+3)
cdq
mov ebx,var+3
idiv ebx
mov edi,eax
mov eax,c //c1=c/(var+4)
cdq
mov ebx,var+4
idiv ebx
mov edx,eax
// left= (a1-b1-c1)^2
mov eax,esi
sub eax,edi
sub eax,edx
imul eax,eax
mov left_a,eax
// (a1*a1)+(b1*b1)+(c1*c1)-2*a1*b1-2*a1*c1+2*b1*c1
mov eax,esi // a1^2
imul eax,eax
mov ebx,edi // b1^2
imul ebx,ebx
mov ecx,edx // c1^2
imul ecx,ecx
add eax,ebx // a1^2+b1^2+c1^2
add eax,ecx
mov ebx,esi // 2*a1*b1
mov ecx,edi
imul ebx,2
imul ebx,ecx
sub eax,ebx
mov ebx,esi //2*a1*c1
mov ecx,edx
imul ebx,2
imul ebx,ecx
sub eax,ebx
mov ebx,edi //2*b1*c1
mov ecx,edx
imul ebx,ecx
imul ebx,2
add eax,ebx
mov right_a,eax
}
// Вывод результатов
printf("Result (C++) Right and Left: %i = %i\n",left,right);
printf("Result (ASM) Right and Left: %i = %i\n",left_a,right_a);
return 0;
}Решение задачи: «Проверка на переполнение при вычислении выражения»
textual
Листинг программы
#include <stdio.h>
#include <iostream>
using namespace std;
#define var 14
int err, err_la,y;
int main()
{
setlocale (LC_CTYPE, "rus");
int a,b,c,a1,b1,c1,left,right,left_a,right_a;
err=0;
printf("Введите переменные a, b, c для выражения (a-b-c)^2 = a^2+b^2+c^2-2ab-2ac+2bc\n");
scanf("%i%i%i",&a,&b,&c);
a1=a/(var+2);
b1=b/(var+3);
c1=c/(var+4);
err = 0;
left = y;
right = ((a1*a1)/(b1))-((b1*b1)/a);
__asm{
mov err_la,0
mov eax,a //a1=a/(var+2)
cdq
mov ebx,var+2
idiv ebx
mov a1,eax
mov eax,b //b1=b/(var+3)
cdq
mov ebx,var+3
idiv ebx
mov b1,eax
mov eax,c //c1=c/(var+4)
cdq
mov ebx,var+4
idiv ebx
mov c1,eax
//
mov eax,a1 // a1^2
imul eax,eax
jo ERROR
mov ebx,b1 // b1^2
imul ebx,ebx
jo ERROR
add eax,ebx // a1^2+b1^2+c1^2
add eax,ecx
jo ERROR
mov ebx,a1 // 2*a1*b1
mov ecx,b1
imul ebx,2
imul ebx,ecx
jo ERROR
sub eax,ebx
mov ebx,a1 //2*a1*c1
mov ecx,c1
imul ebx,2
imul ebx,ecx
sub eax,ebx
jo ERROR
mov ebx,b1 //2*b1*c1
mov ecx,c1
imul ebx,ecx
imul ebx,2
jo ERROR
add eax,ebx
mov right_a,eax
jmp END
ERROR: mov err,1
END:
}
// Вывод результатов
printf("Результаты вычисления на (C++): %i = %i\n",left,right);
if (err==1)
printf("\nОшибка! Переполнение!\n");
else
printf("Результаты вычисления на (ASM): %i = %i\n",left_a,right_a);
return 0;
}
Объяснение кода листинга программы
- Подключение необходимых библиотек для работы с числами и вводом-выводом
- Определение константы var, которая используется в формуле
- Объявление переменных a, b, c, a1, b1, c1, left, right, left_a, right_a иerr_la
- Ввод значений переменных a, b, c с помощью функции scanf
- Вычисление значений a1, b1, c1 с помощью деления a, b, c на var+2, var+3, var+4 соответственно
- Проверка на переполнение при вычислении a1^2, b1^2, a1^2+b1^2+c1^2, 2a1b1, 2a1c1, 2b1c1
- Вычисление значения выражения (a1^2+b1^2+c1^2-2ab-2ac+2bc)/2
- Вывод результатов вычисления на языке C++ и на языке ассемблера
- Проверка наличия ошибки (переполнения) и вывод соответствующего сообщения