LINUX.ORG.RU

В С++ - напиши класс Int, определи для него % чтобы остаток действительно был неотрицательный, в остальном сохрани семантику от int, и везде делай #define int Int

yoghurt ★★★★★
()

А может, проще будет проверять результат, и если он отрицателен, прибавлять к нему делитель?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от yoghurt

> В С++ - напиши класс Int, определи для него % чтобы остаток действительно был неотрицательный, в остальном сохрани семантику от int, и везде делай #define int Int

вас надо писать пособие - как незаметно сделать С++ очень тормознутым, для данного случая просто пишется функция

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

> В С++ - напиши класс Int

Была такая мысль, но нужно на C.

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

> А может, проще будет проверять результат, и если он отрицателен, прибавлять к нему делитель?

Можно, но выглядит как изврат. Сейчас решил временно отказаться от знака «-». Ладно, похоже нужно арифметику самому продумать, ибо кроме отрицательных чисел бывают ещё и большие, а с ними те же проблемы.

FENix
() автор топика

Это не бага, это фича.

      Suppose we divide a by b to give a quotient q and remainder r:
          q = a / b;
          r = a % b;
For the moment, suppose also that b>0.
      What relationships might we want to hold between a, b, p, and q?
1.    Most important, we want q*b + r == a, because this is the relation that defines the remainder.
2.    If we change the sign of a, we want that to change the sign of q, but not the absolute value.
3.    We want to ensure that r>=0 and r<b. For instance, if the remainder is being used as an index to a
      hash table, it is important to be able to know that it will always be a valid index.
      These three properties are clearly desirable for integer division and remainder operations. Unfortu-
nately, they cannot all be true at once.
      Consider 3/2, giving a quotient of 1 and a remainder of 1. This satisfies property 1. What should be
the value of − 3/2? Property 2 suggests that it should be − 1, but if that is so, the remainder must also be
− 1, which violates property 3. Alternatively, we can satisfy property 3 by making the remainder 1, in
which case property 1 demands that the quotient be − 2. This violates property 2.
      Thus C, and any language that implements truncating integer division, must give up at least one of
these three principles.
       Most programming languages give up number 3, saying instead that the remainder has the same sign
as the dividend. This makes it possible to preserve properties 1 and 2. Most C implementations do this in
practice, also.

dccp
()

(a%b + b)%b. но это медленнее.

mqspi
()

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

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

У вас неправильный вариант:

#include <stdio.h>

inline int mod(int x, int y) {
  return x<0 ? x%y+y : x%y;
}

int main(void)
{
	printf("%d %d\n", -8%3, mod(-8, 3));
	return 0;
}


$ gcc test.c
$ ./a.out
-2 1

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

>> В С++ - напиши класс Int, определи для него % чтобы остаток действительно был неотрицательный, в остальном сохрани семантику от int, и везде делай #define int Int

>вас надо писать пособие - как незаметно сделать С++ очень тормознутым, для данного случая просто пишется функция

Вообще-то функции - это тормознуто, а у класса методы отинлайнятся, никто и не отличит. Проверено.

legolegs ★★★★★
()
Ответ на: Это не бага, это фича. от dccp

Плохая это фича:
1) кажись, ещё в пятом классе учат, что остаток есть число неотрицательное.
2) удобство свойства 2 нигде не указано, а неотрицательный остаток имеет массу преимуществ (For instance, if the remainder is being used as an index to a hash table)
3) «Most programming languages give up number 3». Протестую. Навскидку взял python: там всё по-человечески.

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

Вариант правильный:
-8 = -3*3 + 1, т.е. остаток равен единице.

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

> неотрицательный остаток имеет массу преимуществ (For instance, if the remainder is being used as an index to a hash table)

Если тебе нужен индекс, юзай

#define mod(a,b) ( (unsigned int)(a) % (b) )

Что интересно, такой mod аддитивен, т.е. mod(a+c, b)== mod(a,b)+mod(c,b)

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

Можно долго спорить, о том чему учат в школе, но Керниган и Ритчи решили, что этот вариант выгоднее (кстати, была цитата из C Traps and Pitfalls).

> Протестую. Навскидку взял python

Из доступных мне в данный момент языков (Awk, Баш, Си, Си++, Джава, Джаваскрипт, Перл, Питон, ПХП) только перл и питон выдают -8 % 3 = 1. Так что «Most programming languages give up number 3».

> -8 = -3*3 + 1, т.е. остаток равен единице.

Да, вы правы, ошибся.

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

> Можно долго спорить, о том чему учат в школе, но Керниган и Ритчи решили, что этот вариант выгоднее

По-моему это решение в стиле С==высокоуровневый_ассемблер.

Проблема в том, что производители процов реализовывают % по-разному.

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

> И ни разу не баг языка

Не баг, скорее непродуманность. Не думаю, что они взвешивали все за и против и выбрали именно это вариант.

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

> Не баг, скорее непродуманность. Не думаю, что они взвешивали все за и против и выбрали именно это вариант.

Полная продуманность. Или ты хочешь, чтобы они на некоторых платформах сделали (a<0? a%b+b:a%b) -- тогда это уже будет не С. Ибо тормоз.

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

а добавить перед функцией inline религия не позволит?

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

> Вообще-то функции - это тормознуто, а у класса методы отинлайнятся, никто и не отличит. Проверено.

не отличит потому-что С быстрый - попробуйте 1000000 итераций на матрицах прогнать, я уж не говорю про неэффективное выдкление памяти и меньший простор для компилятора при оптимизациях

п.с. про inline функции уже не раз написали

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

>не отличит потому-что С быстрый

Классов в си нет.

>попробуйте 1000000 итераций 

ну так я и пробовал.

class MyInt {
int val;
public:
explicit MyInt(int newval):val(newval) {}
MyInt operator+(const MyInt & other) {  return MyInt(val+other.val); }
//и т.д.
};

Если компилировать с оптимизациями - разницы нет. Вообще. Так что смело делайте класс и реализуйте свой собственный operator%. Хотя идея с привидением к unsigned явно проще.

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

> Если тебе нужен индекс, юзай

> #define mod(a,b) ( (unsigned int)(a) % (b) )

> Что интересно, такой mod аддитивен, т.е. mod(a+c, b)== mod(a,b)+mod(c,b)

a=1, c=1, b=2 -- не сходится

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

> a=1, c=1, b=2 -- не сходится

ОК, если быть точным -- аддитивен в кольце вычетов по модулю b. Но пугать народ я не стал, надеялся что смысл поймут. И точная формула будет страшнее:

mod( a+c, b ) == mod( mod(a,b)+mod(c,b) , b)

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

И на самом деле аддитивен при двух слагаемых он не будет, только при нечетном числе: 3, 5, 7 ... слагаемых. Так что лучше забить на это.

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

> Хотя идея с привидением к unsigned явно проще.

Подозреваю, что у топикстартера конкретная задача очень просто решается. Как сделать ключ я привел для примера.

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

> Не баг, скорее непродуманность. Не думаю, что они взвешивали все за и против и выбрали именно это вариант.

Я об эту фичу деления спотыкался давным-давно. Но к С в данном случае притензии предявить нельзя. Разве что к С++ -- почему int не сделали классом, чтобы сразу у него можно было перегрузить %.

www_linux_org_ru ★★★★★
()

То ли дело коммон лисп, хаскель и питон. Тут везде Ъ-остаток.

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

> В С++ - напиши класс Int

А, вы наверное один из команды OO.org!

sv75 ★★★★★
()

> (-1) % 5 == -1
> что неверно с точки зрения арифметики


Похоже, здесь арифметика неоднозначна. Вот из Википедии (http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_(%D0%...):

"деление целых чисел с остатком определяется по-разному. В одном случае, (так же как и без остатка) рассматривают сначала модули и в результате остаток приобретает тот же знак, что делитель или делимое (например, − 7 / ( − 3) = 2 с остатком (-1)); в другом случае понятие остатка напрямую обобщается и ограничения заимствуются из натуральных чисел".

Да, и что только люди не делают, лишь бы не использовать Фортран :-)

Вот тут:
http://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D1%8...
в Википедии есть очень интересная табличка о том, как организовано деление с остатком в разных языках.

Обратите внимание на приятный подход Фортрана и Ады.

Так что если нужно решать математические задачи, то почему бы не использовать предназначенный для этого современный Фортран-2003? Это уже совсем не тот общеизвестный Фотран-77 :-)

Заодно посоветую посмотреть на математическую часть Ады-2005. Например, как там сделано округление.

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