2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Контроль переполнения
Сообщение02.04.2007, 20:46 


02/04/07
2
В общем, проблема следующая - программа, реализует некоторый класс (скажем, рациональных чисел, числитель и знаменатель должны храниться в int ) и при всех операция должно диагностироваться переполнение .
Как контролировать переполнение при сложении (двух) int'ов я знаю -
смотрим, если числа были одного знака, а сумма с любым из слагаемых уже разного знака, то все - переполнение.
То есть код там следующий:
Код:
int s=0;//сумма
int x;//очередное слагаемое
if( ((x^s)>=0) && (s^(s+x))<0 ){//переполнение}

С вычитанием, по-видимому , нечто очень похожее.
А вот для умножения что-то аналогичное сделать не получается.
Помогите разобраться, пожалуйста.

 Профиль  
                  
 
 
Сообщение03.04.2007, 08:35 
Супермодератор
Аватара пользователя


29/07/05
8248
Москва
Простое решение заключается в том, чтобы использовать 64-битные переменные (тип называется __int64, уточните в справочной системе). Все операции делать над этими числами, затем проверять переполнение, если все нормально - переводить обратно в обычный int.

 Профиль  
                  
 
 
Сообщение03.04.2007, 10:43 


21/03/06
1545
Москва
Можно сделать что-то типа:

Код:
#include <limits.h>
...

int summ (const int a, const int b, int *res)
{
  //Тут для наглядности не морочимся с отрицательными a и b.
  //В реальной программе конечно необходимо рассмотреть случаи когда a<0 и b<0
  if( INT_MAX - a <= b)
    return 0;

  *res = a+b;
  return 1;
}

int mult (const int a, const int b, int *res)
{
  if( INT_MAX/abs(a) <= abs(b) )
    return 0;

  *res = a*b;
  return 1;
}


Т.к. вы используете именованную константу INT_MAX, и стандартный заголовочный файл limits.h, где она должна быть описана, программа получается переносимой.

Вариант 2: В начале программы самостоятельно определить максимально возможное число, хранимое в int, и использовать его также, как в варианте 1.

 Профиль  
                  
 
 
Сообщение03.04.2007, 17:57 


02/04/07
2
В принципе с более широким типом данных идея понятна и это даже работает.
Мне именно хотелось узнать как это можно реализовать, что называется, более эффективно, ведь не секрет, что битовые операции выполняются много быстрее (как я написала в случае сложения) , чем вся эта канитель с приведением типов. Собственно, вопрос как раз в этом и состоит :wink:

 Профиль  
                  
 
 
Сообщение03.04.2007, 21:39 
Супермодератор
Аватара пользователя


29/07/05
8248
Москва
Не факт, на самом деле. Условный переход, скрытый в &&, может скушать весь выигрыш от более быстрых операций.

 Профиль  
                  
 
 
Сообщение04.04.2007, 02:06 
Заслуженный участник
Аватара пользователя


17/10/05
3709
:evil:
Я встречал (довольно часто) inline-функции, со входом int и выходом int64. Специально для подобных нужд.

Мордюкова писал(а):
как это можно реализовать, что называется, более эффективно,

Когда речь идет «всурьез», такого рода вычисления выписывают на ассемблере, где обычно умножение выдает результат двойной точности, либо флаг переполнения (либо оба). Тоже самое относится и к сложению/вычитанию.

PAV писал(а):
Условный переход, скрытый в &&, может скушать весь выигрыш от более быстрых операций.

Можно написать, конечно, для $s = a + b$ формУлу $\text{ofl} = ((a \oplus b) \wedge (b \oplus s)) < 0$. Может, она даже будет быстрой. Все равно, выигрыша (по сравнению с &&) в большинстве случаев невелик (если переход происходит, то не важно когда. А если не происходит, то он стоит недорого). Но, скажем, при векторных вычислениях этот трюк может помочь.

 Профиль  
                  
 
 Re: Контроль переполнения
Сообщение01.01.2011, 14:06 


01/01/11
1
не проще вставку ассемблерную сделать нечто вроде:

asm
mov ax,первый операнд
mov bx,второй операнд
add ax,bx
jnc .m1
взвести флаг
.m1:
end;

?

 Профиль  
                  
 
 Re: Контроль переполнения
Сообщение03.02.2013, 01:08 


03/02/13
1
Копаем код в оллеdbg - видим умножение происходит со знаком - IMUL.
Проверка с использованием Ассемблера - открываем 35 страницу Зубкова С.В. "Assembler для DOS, Windows и UNIX"
Написано - если происходит переполнение, то флаги OF и CF будут равны "1" проверяется последовательно двумя командами сравнения соответствующих флагов указанных выше jc и jo.
Делаем после кода умножение (*z) проверочку с помощью ассемблерной вставочки.
Код:
            buff=(FunctionRecurFacktorial(z-1)*z);
            _asm
            {
           jc OverProb;
           jmp L1
OverProb:jo OverYES
           jmp ExitLabel
   
OverYES:  mov eax,-1
           mov zz,-1
ExitLabel:
            }
            if(zz==0)rez=buff;
            else {rez=0;printf("OVERflov");}



Вот полный код программки для вычисления факториала, где задается верхняя граница, код сырой, я баловался с рекурсией
Код:
#include <stdio.h>
//#include<cmath>



main ()
{
   unsigned int FaK(int z);
   int x,i=-6;
   printf("vvedite verch gran:");
   scanf("%d",&x);
   while (i<=x)
   {
      printf("%4d! =  %d\n",i, FaK(i));
      i++;
   }
}
unsigned FaK(int z)
{
   unsigned int rez=999,zz=0,buff;
   if (z<0)
   {
      printf("ErroR");
      rez=-1;
   }
   if (0==z) rez=1;
   if (z>0)
   {
            
            buff=(FaK(z-1)*z);
            _asm
            {
    jc Lok;
    jmp L1
lok: jo Lok2
    jmp L1
   
Lok2:mov eax,-1
    mov zz,-1
L1:
            }
            if(zz==0)rez=buff;
            else {rez=0;printf("OVERflov");}
   }
   return rez;
}

для контроля корректности результатов - При вычислении более 12 итераций происходит переполнение

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 8 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group