LINUX.ORG.RU

Помогите определить эквивалентны ли ...


0

2

«Попробуем написать очень простую программу (а на самом деле функцию - какая разница?), которая вычисляет среднее значение двух аргументов:

int avg(int a, int b) { return (a + b) / 2; } Правильно?

Вы конечно узнали язык Си, и скорее всего не заметили в чем тут подвох. Не отчаивайтесь: согласно одному исследованию, подобные вещи не замечают 95% программистов. Дело в том, что при сложении (a + b) может произойти переполнение, когда как результат - ведь он же среднее двух аргументов - никогда не должен переполняться. Значит надо переписать функцию так, чтобы она не была подвержена переполнениям:

int avg(int a, int b) { return a + (b - a) / 2; } Правильно?»

Из статьи Клиника плохого кода. http://bugtraq.ru/library/programming/badcode.html

Собственно вопрос таков, разве выражение (a + b) /2 === a + (b -a) / 2 по результату ?

P.S Если решите что мне нужна самому нужна операция операция на мозгу, так и быть. Но хотелось бы знать почему =)


Собственно вопрос таков, разве выражение (a + b) /2 === a + (b -a) / 2 по результату ?

пхп головного мозга!? ;)

P.S. Да, по результату аналогичны. Правда как это спасёт от buffer owerflow - не понимаю :)

chinarulezzz ★★
()

> не была подвержена переполнениям:

int avg(int a, int b) { return a + (b - a) / 2


Знатное деление на ноль.

geekless ★★
()
Ответ на: комментарий от geekless

*бьюсь об стол головой, просыпая пепел с шевелюры на колени и тапки*
Да, про int я поспешно забыл =(

Terrens
()
Ответ на: комментарий от xapienz

*внимательно смотрит на название раздела, а потом на три коммента, авторы которых считают, что 3/2+7/2 = 5

Обалдеть. Ночной ЛОР прекрасен сегодня.

geekless ★★
()
Ответ на: комментарий от geekless

Сходил по ссылке: «Уже лучше, но опять не то. На этот раз мы забыли, что аргументы могут быть отрицательными.» Всё-таки деление на ноль не у автора статьи, а у ТС-а.

geekless ★★
()
Ответ на: комментарий от chinarulezzz

>>P.S. Да, по результату аналогичны. Правда как это спасёт от buffer owerflow - не понимаю :)

Слабо представить косоугольную трапецию в комнате с низким потолком?

mclaudt
()
Ответ на: комментарий от chinarulezzz

Блин арифметику забыл, а ведь в правом выражениии вынесли за скобку =)

Sundro
() автор топика
Ответ на: комментарий от chinarulezzz

> а, да, компьтерная арифметика, вычисления в целых числах, дополнительный код, ВУЗ, первый курс ... Забывается всё, забывается)

Очевидный фикс.

geekless ★★
()
Ответ на: комментарий от chinarulezzz

>>фантазия хорошо работает на глупости

Не факт. Когда поумнеешь, обнаружишь, что фантазия заработала ещё лучше.

mclaudt
()

Да хрен с ним, с переполнением. Но разве деление будет не целочисленное? Там же к double нужно привести еще. Или это только в жабке так.

dizza ★★★★★
()
Ответ на: комментарий от mclaudt

т.е. ты хочешь сказать что данный фрагмент спасет от ошибки? Или я как-то чересчур увидел интеллектуальный подъ%б с твоей стороны? ))

chinarulezzz ★★
()
Ответ на: комментарий от chinarulezzz

Если ты не видишь, почему спасает, то подкоп был оправдан.

Геометрический смысл среднего двух чисел прививают еще в детском саду.

mclaudt
()
Ответ на: комментарий от mclaudt

Если ты не видишь, почему спасает, то подкоп был оправдан.

не вижу, не спасает. Хватает одного негативного аргумента для переполнения.

Геометрический смысл среднего двух чисел прививают еще в детском саду.

ну тогда беги скорей, а то опоздаешь же!

chinarulezzz ★★
()

int avg(int a, int b) { return (a + b) / 2; } Правильно?

Вы конечно узнали язык Си, и скорее всего не заметили в чем тут подвох. Не отчаивайтесь: согласно одному исследованию, подобные вещи не замечают 95% программистов. Дело в том, что при сложении (a + b) может произойти переполнение, [..]

дело в том, что, блджад, (a+b)/2 в общем случае даёт тип float, а не нифига не int, а на переполнение покласть

shty ★★★★★
()
Ответ на: комментарий от chinarulezzz

>>не вижу, не спасает. Хватает одного негативного аргумента для переполнения.

Не передергивай. Речь шла об уберегании от переполнения выражения (a+b)/2.

mclaudt
()
Ответ на: комментарий от mclaudt

Речь шла об уберегании от переполнения выражения (a+b)/2.

нет, не этого выражения, а этого:

a + (b -a) / 2

Я недоумевал как это может спасти от переполнения. Так что прежде чем лезть спорить, удостоверься что хотя бы правильно прочёл исходное сообщение. ;)

chinarulezzz ★★
()
Ответ на: комментарий от chinarulezzz

>>Я недоумевал как это может спасти от переполнения. Так что прежде чем лезть спорить, удостоверься что хотя бы правильно прочёл исходное сообщение.

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

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

mclaudt
()
Ответ на: комментарий от mclaudt

Речь в примере шла именно об переполнении в случае одинаковых знаков.

Сам только что придумал?

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

По ссылке? Я отвечал на сообщение, а не на статью по ссылке. Все что можно было понять из сообщения - на то я и ответил.

Так что прежде чем лезть со своими удивлениями, удостоверься, что хотя

бы правильно понял контекст разговора.

Лоханулся с наездом ты короче) Обосрался - сделал вид что так и надо? ))

chinarulezzz ★★
()
Ответ на: комментарий от chinarulezzz

>>По ссылке? Я отвечал на сообщение, а не на статью по ссылке.

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

mclaudt
()
Ответ на: комментарий от Waterlaz

У меня туго с -1 -2 например. Тестировал на Java. А что говорит С?

vertexua ★★★★★
()
Ответ на: комментарий от Waterlaz

Хоть один разумный человек. Хотя по делу в проце флаг переполнения/переноса из коробки.

bga_ ★★★★
()
int aver(int a, int b)
{
	return abs(a) < abs(b) ? a + (b - a) / 2 : b + (a - b) / 2;
}

индусятина :)

backbone ★★★★★
()

Анонимное сообщество анонимусов-программистов возражает!!!

Несправедливые обвинения 90% анонимных программистов в «недалекости» это самый настоящий экстремизм и геноцид анонимусов-программистов, которые давно представляют собой социальную группу!!!

Дело в том, что следуя одному из стилей написания функций, заботу о проверке параметров функции на соответствие явным и неявным предположениям внутри тела функции должен взять на себя клиентский код.

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

Если по делу, то рассмотрев различные варианты а и b из промежутка [-w,w-1], где w=2^M, тривиальными рассуждениями получим:

a+b из промежутка [-2w, 2(w-1)]; b-a из промежутка [-2w+1, 2w-1]; т.е. в обоих случаях переполнение теоретически возможно;

Если a и b из промежутка [0,w-1], то: a+b из промежутка [0, 2(w-1)]; b-a из промежутка [-w+1, w-1]; во втором случае переполнения не возникает в отличие от первого;

Если a и b из промежутка [-w,-1], то: a+b из промежутка [-2w, -2]; b-a из промежутка [-w+1, w-1]; во втором случае переполнения не возникает в отличие от первого;

Если a из промежутка [0,w-1], b из промежутка [-w,-1], то: a+b из промежутка [-w, w-2]; b-a из промежутка [-2w+1, -1]; в первом случае переполнения не возникает в отличие от второго;

Если a из промежутка [-w,-1], b из промежутка [0,w-1], то: a+b из промежутка [-w, w-2]; b-a из промежутка [-1, 2w-1]; в первом случае переполнения не возникает в отличие от второго;

Вывод очевиден - даже в самом параноидальном случае, когда avg сама беспокоится об переполнении аргументов, одного ветвления будет достаточно (и не надо рассказывать сказок, что без него будет быстрее - лучше выберите более быстрый алгоритм). Разумеется, надо удостовериться что целочисленное деление на 2 работает как ожидается для отрицательных чисел, т.е. -1/2=0.

anonymous
()
Ответ на: комментарий от anonymous

Анонимус!!! Не позорь анонимусов!!!

Скорее всего надо использовать формулы a+(b-a)/2 или b+(a-b)/2 в случае чисел одного знака, в зависимости от соотношений b-a>0 или нет.

Кстати, сравнение модулей не годится - тоже может быть переполнение при вычислении модуля числа. У нас же паранойя!!!

Ситуация требует особенной проверки!!!

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.