напишите функцию на сях (очень простую)
может, это и изврат, но я бы:
записал в память дабл
считал бы ее как несколько интов
посчитал бы количество нулей
записал в память дабл
считал бы ее как несколько интов
посчитал бы количество нулей
code плиз
думать некогда, гарай тут умирает, надо отнести преподу
думать некогда, гарай тут умирает, надо отнести преподу
#include <stdio.h>
int s( double val )
{
int i, j;
int ret = 0;
union
{
double v;
char c[ sizeof( double ) ];
} a;
a.v = val;
for ( i = 0; i < sizeof( double ); i++ )
{
for ( j = 0; j < 8; j++ )
{
ret += a.c[i] & 1;
a.c[i] >>= 1;
}
}
return ret;
}
int main
{
printf( "%d\n", s( 1.0 ) ) ;
}
не проверял, но, надеюсь, сработает. Здесь учтено, что длина дабла нацело делится на длину инта. Можно, в принципе, снять ограничение, если вместо unsigned int писать unsigned char.
int nNonZero(unsigned int a)
{
int i = 0;
int c;
for (c = 0; c < sizeof(unsigned int) * 8; c++)
i += (a >> c) % 2;
return i;
}
int foo(double x)
{
int num = 0;
for (int c = 0; c < sizeof(double)/sizeof(unsigned int); c++)
num += nNonZerounsigned int*(&x + c * sizeof(unsigned int;
return num;
}
Неверно. Надо убрать int c из цикла, и + с * sizeof( unsigned int ). Причем указатель &x вначале привести к указателю на char. Или скобки по другому расставить.
с ансайнт интом согласен, опечатка. А про инт цэ не понял.
C не умеет объявлять таким образом переменную.
int f(double d)
{
int cnt = 0;
int i,j;
for (i=0; i<sizeof(double); ++i)
for (j=0; j<8; ++j)
cnt += char*)&d)[i] >> j) & 1;
return cnt;
}
я знаю. Но, во-первых, подозреваю, что и на пласпласе задачу примут. Во-вторых, мне так писать экономнее, а привести синтаксис к сишному сможет любой.
Да, перед char лучше приписать unsigned.
гарай уже ушел
можно расслабица
можно расслабица
Я гоню, или должен быть unsigned char?
union
{
double v;
char c[ sizeof( double ) ];
} a;
a.v = val;
for ( i = 0; i < sizeof( double ); i++ )
{
for ( j = 0; j < 8; j++ )
{
ret += a.c[i] & 1;
a.c[i] >>= 1;
}
}
Кстати оптимизация:
По идее на случайном инпуте должна оптимизировать в 1.7 раза.
for ( i = 0; i < sizeof( double ); i++ )
{
while (a.c[i] > 0)
{
ret += a.c[i] % 2;
a.c[i] /= 2;
}
}
По идее на случайном инпуте должна оптимизировать в 1.7 раза.
C не умеет объявлять таким образом переменную.С-99 умеет.
Я гоню, или должен быть unsigned char?Гонишь.
желателен
чтобы не думать, как там реализуется % для отрицательных чисел на данной архитектуре
чтобы не думать, как там реализуется % для отрицательных чисел на данной архитектуребыстрее будет так:
есть еще более быстрый способ - но он уже извратный - его так с ходу не вспомнить.
если бить double на инты, а не char-ы, то в среднем будет еще быстрее.
while (a.c[i] > 0)
{
bitCount++;
a.c[i] = a.c[i] & (a.c[i]-1);
}
есть еще более быстрый способ - но он уже извратный - его так с ходу не вспомнить.
Просветите меня, разве это:
a.c[i] /= 2оптимизация относительно
a.c[i] >>= 1на IA-32?
имхо каким бы комплиятором не пользовался, он заменит деление на сдвиг
О % там речи не шло.
Знаковый сдвиг, насколько я знаю, везде реализован подходящим образом.
Знаковый сдвиг, насколько я знаю, везде реализован подходящим образом.
Если будет signed char, то при сдвиге левая единица будет размножаться.
для жесткого for-а с 8 - это не страшно, для остальных более быстрых алгоритмов - это будет проблемой.
для жесткого for-а с 8 - это не страшно, для остальных более быстрых алгоритмов - это будет проблемой.
Странно, а почему на разные?
int main{
int a=1024, b=1024;
a /= 2;
b >>= 1;
exit(0);
} .file "main.cpp"
.version "01.01"
gcc2_compiled.:
.text
.p2align 2,0x90
.globl main
.type main,@function
main:
pushl %ebp
movl %esp,%ebp
subl $24,%esp
movl $1024,-4(%ebp)
movl $1024,-8(%ebp)
movl -4(%ebp%eax
cltd
movl %edx,%ecx
shrl $31,%ecx
leal (%ecx,%eax%edx
movl %edx,%eax
sarl $1,%eax
movl %eax,-4(%ebp)
sarl $1,-8(%ebp)
addl $-12,%esp
pushl $0
call exit
addl $16,%esp
xorl %eax,%eax
jmp .L2
.p2align 2,0x90
.L2:
leave
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) cplusplus 2.95.4 20020320 [FreeBSD]"
> если бить double на инты, а не char-ы, то в среднем будет еще быстрее.
Я пытался, но не особо получилось. Мне кажется разбивать double на intы означает опираться на конкретную реализацию переменных с плавающей точкой. А union{} предложенный Антоном, плевал на реализацию double.
> есть еще более быстрый способ - но он уже извратный - его так с ходу не вспомнить.
Типа вот этого?
По-моему для double не прокатит, потому что фиг знает что он из себя представляет.
Я пытался, но не особо получилось. Мне кажется разбивать double на intы означает опираться на конкретную реализацию переменных с плавающей точкой. А union{} предложенный Антоном, плевал на реализацию double.
> есть еще более быстрый способ - но он уже извратный - его так с ходу не вспомнить.
Типа вот этого?
#define g21 0x55555555ul /* = 0101_0101_0101_0101_0101_0101_0101_0101 */
#define g22 0x33333333ul /* = 0011_0011_0011_0011_0011_0011_0011_0011 */
#define g23 0x0f0f0f0ful /* = 0000_1111_0000_1111_0000_1111_0000_1111 */
static __inline u_char
bit_count(uint32_t v)
{
v = (v & g21) + v >> 1) & g21);
v = (v & g22) + v >> 2) & g22);
v = (v + (v >> 4 & g23;
return (v + (v >> 8) + (v >> 16) + (v >> 24 & 0x3f;
По-моему для double не прокатит, потому что фиг знает что он из себя представляет.
Мне кажется разбивать double на intы означает опираться на конкретную реализацию переменных с плавающей точкой.
По-моему для double не прокатит, потому что фиг знает что он из себя представляет.Бля
> Я пытался, но не особо получилось. Мне кажется разбивать double на intы означает опираться на конкретную
> реализацию переменных с плавающей точкой. А union{} предложенный Антоном, плевал на реализацию double.
можно сделать что-то такое страшное.
> реализацию переменных с плавающей точкой. А union{} предложенный Антоном, плевал на реализацию double.
можно сделать что-то такое страшное.
double v;
int * i = (int*)&v;
unsigned short * si = (..)&v;
unsigned byte * bi = (..)&v; //приведения можно и через union сделать - будет быстрее
int len = sizeof(v);
int pos = 0;
while(len - pos >= sizeof(unsigned int
{
bitCount+=CalcBitsInInt(*(i+pos;
pos += 4;
}
while(len - pos >= sizeof(unsigned short
{
bitCount+=CalcBitsInWord(*(si+pos;
pos += 2;
}
while(len - pos >= sizeof(unsigned byte
{
bitCount+=CalcBitsInByte(*(bi+pos;
pos += 1;
}
насчет сдвига: sar - из-за того, что int юзается.
а деление - хз.
а деление - хз.
> #define g21 0x55555555ul /* = 0101_0101_0101_0101_0101_0101_0101_0101 */
Да, это ОНО.
Да, это ОНО.
Узнал много нового. Похоже на большинстве платформ представление одинаково.
Например, gcc пишут, что всё будет по стандарту if hardware is perfect, но всё равно не определяют __STDC_IEC_559__.
Например, gcc пишут, что всё будет по стандарту if hardware is perfect, но всё равно не определяют __STDC_IEC_559__.
Кстати, если ты такой умный, то скажи в каких константах определено сколько бит отдано под мантиссу и под экспоненту?
Post deleted by
ЗЫ В моём компиляторе
это, видимо
DBL_MANT_DIG // float.h
это, видимоDBL_MANT_DIG // float.h
Так вот непонятно оговаривает ли стандарт значение. На IEEE 754, который первая ссылка в гугле, получается как оговаривает. На самом деле на IEEE754 никто не ссылается. C99 ссылается на IEC 60559, который у меня не получается найти. Есть смутные утверждения, что IEEE754 == IEC 60599.
Народ! Всем спасибо! Я сегодня сдал!
(Лучше поздно чем никогда)
(Лучше поздно чем никогда)
Странно, а почему на разные?
за диплом засел 

Оставить комментарий
kozicin
посчитать количество ненулевых битов в переменной типа Double