Существует множество видов округлений, начиная от простого отбрасывания незначимой части, заканчивая хитрыми симметричными методами. Приму следующие названия для типов округления:
В этом разделе я буду использовать следующие обозначения:
Сдвиги право теряют младшие биты числа, поэтому округление всё равно будет происходить. Здесь я постараюсь изложить аспекты округления в таких случаях.
Примем условное обозначение:
При этом подразумевается, что
то есть сдвиг производит округление до степени двойки, причём показатель степени равен числу битов.
Тут не надо ничего городить — в арифметике со дополнением до двух при сдвиге влево округление вниз происходит само собой.
y = x >> N;
Окгругление вверх тоже достаточно просто, его можно совершить двумя простыми способами:
y = (x+(1 << N-1)-1)>>N
y = -(-x >> N)
1<<N
(1<<N)-1
for(i = 0, S = 0; x<0; x>>1) { if(x&1!=0) S++; }
#define bitno_mod9(b) ((((b)&-(b))%7>>1)+3*(((((b)&-(b))>>2)*7&011111111111)%0777%6>>1)) #define bitno(b) (bitno_mod9(b)+9*bitno_mod9(((((b)&-(b))>>8)*0777&01001001001)%0776))
Вот две функции преобразования целого числа без знака, обладающие парой преимуществ:
Конечно, здесь показан сырые варианты, ограниченный размером числа и выводящий всегда одинаковое число знаков, но её несложно расширить и адаптировать.
16-битная версия (ограничение до 999).
char * strfu3(char *str, unsigned int x) { int i; x = (x<<2) + ((25*x)>>8) + 2; // x*(2**12/10**3) for(i = 0; i<3; i++) { x = x * 10; *(str++) = '0' + (x>>12); x &= 0xFFF; } *str = 0; return str; }
32-битная версия (ограничение до 999999).
char * strfu6(char *str, unsigned int x) { int i; x = (x<<8) + ((3183*x)>>8) + 128; // x*(2**28/10**6) for(i = 0; i<6; i++) { x = x * 10; *(str++) = '0' + (x>>28); x &= 0xFFFFFFF; } *str = 0; return str; }
Наивная (каноническая) запись | Гик-запись | Комментарий |
---|---|---|
NULL | 0 | Совершенно законно, ибо постандарту NULL=(void *)0 |
if(0!=x) | if(x) | if сравнивает результат с нулём всегда |
0==x | !x | Кроме указателей? |
0!=x | !!x | Если x — условие, то просто x |
if(!f) y++ | y += !f | Точно так же – и =- |
if(f) y++ | y += f | |
f?a:0 | -x&a | |
f?a:b | b^-x&(a^b) |