как посчитать без переполнения
От: piAnd Россия  
Дата: 25.08.06 20:49
Оценка:
Есть переполнение при таком расчете:
int X1, X2, X3, X4, X5, X6, X7, X8; //32bit


далее считаем вот такого типа выражения (переполнения еще нет)
a = X1*X2 + X3*X4;
b = X5*X6 + X7*X8;


а теперь нужно проверить условие
(X1*X3 + X2*X4)*a >= (X5*X7 + X6*X8)*b //вот тут переполнение


Как бы сделать проверку условия, желательно с тем же типом int (32bit)?
Re: как посчитать без переполнения
От: RSDN_YG Россия  
Дата: 26.08.06 03:42
Оценка:
Здравствуйте, piAnd, Вы писали:

A>Есть переполнение при таком расчете:

A>
A>int X1, X2, X3, X4, X5, X6, X7, X8; //32bit
A>


A>далее считаем вот такого типа выражения (переполнения еще нет)

A>
A>a = X1*X2 + X3*X4;
A>b = X5*X6 + X7*X8;
A>


A>а теперь нужно проверить условие

A>
A>(X1*X3 + X2*X4)*a >= (X5*X7 + X6*X8)*b //вот тут переполнение
A>


A>Как бы сделать проверку условия, желательно с тем же типом int (32bit)?


А просто преобразовать неравенство?
(X1*X3 + X2*X4) / (X5*X7 + X6*X8) >= b / a;

underflow будет?
Re[2]: как посчитать без переполнения
От: mcf  
Дата: 26.08.06 08:29
Оценка:
Здравствуйте, RSDN_YG, Вы писали:

RSD>Здравствуйте, piAnd, Вы писали:


A>>а теперь нужно проверить условие

A>>
A>>(X1*X3 + X2*X4)*a >= (X5*X7 + X6*X8)*b //вот тут переполнение
A>>


A>>Как бы сделать проверку условия, желательно с тем же типом int (32bit)?


RSD>А просто преобразовать неравенство?

RSD>
RSD>(X1*X3 + X2*X4) / (X5*X7 + X6*X8) >= b / a;
RSD>

RSD>underflow будет?

Ээээ... хрен редьки не слаще, бесполезно в общем, нужен 64 бит.
Re: как посчитать без переполнения
От: v_m  
Дата: 26.08.06 12:01
Оценка:
26 августа 2006 00:49 piAnd wrote:

> Есть переполнение при таком расчете:

>
> int X1, X2, X3, X4, X5, X6, X7, X8; //32bit
>

>
> далее считаем вот такого типа выражения (переполнения еще нет)
>
> a = X1*X2 + X3*X4;
> b = X5*X6 + X7*X8;
>

>
> а теперь нужно проверить условие
>
> (X1*X3 + X2*X4)*a >= (X5*X7 + X6*X8)*b //вот тут переполнение
>

>
> Как бы сделать проверку условия, желательно с тем же типом int (32bit)?
c = x1*x3 + x2*x4;
d = x5*x7 + x6*x8;
ac_h = (a * c) >> 32;
ac_l = ((a * c) — (ac_h << 32)) >> 32; // 1
bd_h = (b * d) >> 32;
bd_l = ((b * d) — (bd_h << 32)) >> 32; // 2

if (ac_h > bd_h) true;
else if (ac_h == bd_h && ac_l > bd_l) true
else false

1 и 2 за счёт временного расширения типов должно сработать

Либо использовать софтовую реализацию int64_t
Posted via RSDN NNTP Server 2.0
Re[2]: как посчитать без переполнения
От: v_m  
Дата: 26.08.06 12:06
Оценка:
26 августа 2006 16:01 v_m wrote:

> ac_l = ((a * c) — (ac_h << 32)) >> 32; // 1

> bd_h = (b * d) >> 32;
> bd_l = ((b * d) — (bd_h << 32)) >> 32; // 2
>
> if (ac_h > bd_h) true;
> else if (ac_h == bd_h && ac_l > bd_l) true
> else false
>
> 1 и 2 за счёт временного расширения типов должно сработать
В 1 и 2 финальные сдвиги лишние :*)
Posted via RSDN NNTP Server 2.0
Re[2]: как посчитать без переполнения
От: mcf  
Дата: 26.08.06 12:26
Оценка:
Здравствуйте, v_m, Вы писали:

v_m>26 августа 2006 00:49 piAnd wrote:


v_m> c = x1*x3 + x2*x4;


Уже здесь ошибка, дальнейшее не имеет смысла.
Re[3]: как посчитать без переполнения
От: v_m  
Дата: 26.08.06 12:54
Оценка:
26 августа 2006 16:26 mcf wrote:

> Здравствуйте, v_m, Вы писали:

>
> v_m>26 августа 2006 00:49 piAnd wrote:
>
> v_m> c = x1*x3 + x2*x4;
>
> Уже здесь ошибка, дальнейшее не имеет смысла.
Без диапазона входных данных точно сказать нельзя. К тому же, в исходном
письме, кажется, переполнение было при ещё одном умножении суммы
произведений.
Posted via RSDN NNTP Server 2.0
Re[4]: как посчитать без переполнения
От: piAnd Россия  
Дата: 26.08.06 15:06
Оценка:
Здравствуйте, v_m, Вы писали:
v_m> Без диапазона входных данных точно сказать нельзя. К тому же, в исходном
v_m>письме, кажется, переполнение было при ещё одном умножении суммы
v_m>произведений.
Диапазон такой, что вычисление x*x + x*x идет без overflow
v_m>c = x1*x3 + x2*x4;
v_m>d = x5*x7 + x6*x8;
v_m>ac_h = (a * c) >> 32;
v_m>ac_l = ((a * c) — (ac_h << 32));
v_m>bd_h = (b * d) >> 32;
v_m>bd_l = ((b * d) — (bd_h << 32));


a*c — это уже с overflow, сравнение старших ac_h, bd_h что будет означать?, они ж уже overflow.
Re[5]: как посчитать без переполнения
От: v_m  
Дата: 26.08.06 16:44
Оценка:
26 августа 2006 19:06 piAnd wrote:

> a*c — это уже с overflow, сравнение старших ac_h, bd_h что будет

> означать?, они ж уже overflow.
Да, overflow, но не сразу после операции умножения Результатом команды
imul является пара edx:eax. Впрочем, сейчас проверил, компилятор (gcc
4.1.4) на edx никакого внимания не обращает и оперирует после перемножения
только с eax, а жаль. Можно сказать, что overflow получается искуственный.

ps Вспомнил просто, что совершенно спокойно считал нормали (обсуждаемое
переполнение в формуле, очень похожей на расчёт нормали) с привлечением
ассемблера.
Posted via RSDN NNTP Server 2.0
Re[6]: как посчитать без переполнения
От: Vain Россия google.ru
Дата: 26.08.06 17:05
Оценка:
Здравствуйте, v_m, Вы писали:

v_m>imul является пара edx:eax. Впрочем, сейчас проверил, компилятор (gcc

v_m>4.1.4) на edx никакого внимания не обращает и оперирует после перемножения
edx:eax это 64bit, если исходные типы 32bit, то естественно используется токо eax, если хотите и edx, то под msvc это __int64
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[7]: как посчитать без переполнения
От: v_m  
Дата: 26.08.06 17:13
Оценка:
26 августа 2006 21:05 Vain wrote:

> edx:eax это 64bit, если исходные типы 32bit, то естественно

> используется токо eax,
Когда производится счет, компилятор может временно расширить тип.
Собственно, поэтому у меня и появилась мысль, что компилятор так и сделает,
ибо очевидно, что int * int легко может оказаться больше int.
Posted via RSDN NNTP Server 2.0
Re[8]: как посчитать без переполнения
От: mcf  
Дата: 26.08.06 18:23
Оценка:
Здравствуйте, v_m, Вы писали:

v_m>26 августа 2006 21:05 Vain wrote:


>> edx:eax это 64bit, если исходные типы 32bit, то естественно

>> используется токо eax,
v_m> Когда производится счет, компилятор может временно расширить тип.
v_m>Собственно, поэтому у меня и появилась мысль, что компилятор так и сделает,
v_m>ибо очевидно, что int * int легко может оказаться больше int.

Нифига не очевидно.
Если компилятор это учитывает, то это ошибка, так не должно быть.
И пусть попробует меня заставить не переполнить int
Re[9]: как посчитать без переполнения
От: v_m  
Дата: 26.08.06 21:24
Оценка:
26 августа 2006 22:23 mcf wrote:

> сделает, v_m>ибо очевидно, что int * int легко может оказаться больше int.

> Нифига не очевидно.
> Если компилятор это учитывает, то это ошибка, так не должно быть.
Почему же ошибка? Он может досчитать оставшееся выражение и потом спокойно
обрезать до int.

> И пусть попробует меня заставить не переполнить int

А если вместо int будет short int, в один 32-битный регистр всё влезет, это
тоже будет ошибкой?
Posted via RSDN NNTP Server 2.0
Re[10]: как посчитать без переполнения
От: IceStudent Украина  
Дата: 28.08.06 05:14
Оценка:
Здравствуйте, v_m, Вы писали:

v_m> Почему же ошибка? Он может досчитать оставшееся выражение и потом спокойно

v_m>обрезать до int.
Бывают алгоритмы, в которых такой метод являлся бы ошибкой. Хотя это скорее исключение.
--
wbr, icestudent
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.