Как проверить число на чётность не чётность?

Статус
В этой теме нельзя размещать новые ответы.

whirlwind

TDD infected, paranoid
Вообще то что if(x%2 != 0) более читабельно нежели if(x%2) вопрос ИМХО спорный и зависит сугубо от контекста. Это как с упрощением уравнений, если у нас два значения известны, то зачем нам их явно записывать - что бы глаза мозолили? Гораздо удобнее упростить.

Вариант где в условии два неизвестных несомненно выглядит малопонятно if ( x % y ) - как уравнение, в котором одни неизвестные - смахивает на нерешаемое. Такой случай должен записываться как if ( x % y != 0 ) или аналогично. Там же где результат вычисления может быть сведен к булеву значению, выражение должно сокращаться для удобства восприятия. Например результатом логического & отнюдь не является булево значение, однако проверка на четность может дать только два исхода - чет/нечет. Написание в этом случае лишних кракозябр наоборот запутывает - непонятно что же мы там все таки проверяем. Если мы получаем результат, то почему не записываем его в переменную, возможно мы проверяем не является ли результат объединения нулевым значением.... И т.д. В итоге смысл выражения в скобках расплывается, а это не способствует восприятию. В общем ИМХО - все зависит от конкретного частного случая.
 

phprus

Moderator
Команда форума
StUV
Я говорил не об оптимизации процесса разработки, а о времени выполнения такиой конструкции.

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

Кстати если на то пошло то можно сделать голосование и выяснить кто на этом форуме что думает по поводу написания условных операторов и кто ка кпроверяет числа на четность/нечетность. По аналогии с темой http://phpclub.ru/talk/showthread.php?s=&threadid=82484
 

Crazy

Developer
Автор оригинала: Crazy
Остается проверить на gcc. Что я вечером и сделаю. :)
Будем считать, что уже вечер. Ибо я уже дома.

Итак, мой эксперимент.

Файл test1.c:

Код:
int main (int argc, char** argv) {
  int x = argc * 12345;
  printf("%d", (x & 1) ? 5 : 6); 
}
Файл test2.c:

Код:
int main (int argc, char** argv) {
  int x = argc * 12345;
  printf("%d", (x % 2 != 0) ? 5 : 6); 
}
Компиляция производилась gcc с ключами -S -O2.

Результат. Файл test1.s:

Код:
	.file	"test1.c"
gcc2_compiled.:
___gnu_compiled_c:
	.def	___main;	.scl	2;	.type	32;	.endef
.text
LC0:
	.ascii "%d\0"
	.align 4
.globl _main
	.def	_main;	.scl	2;	.type	32;	.endef
_main:
	pushl %ebp
	movl %esp,%ebp
	subl $20,%esp
	pushl %ebx
	movl 8(%ebp),%ebx
	call ___main
	imull $12345,%ebx,%ebx
	addl $-8,%esp
	movl $6,%eax
	testb $1,%bl
	je L3
	movl $5,%eax
L3:
	pushl %eax
	pushl $LC0
	call _printf
	movl -24(%ebp),%ebx
	movl %ebp,%esp
	popl %ebp
	ret
	.def	_printf;	.scl	2;	.type	32;	.endef
Файл test2.s:

Код:
	.file	"test2.c"
gcc2_compiled.:
___gnu_compiled_c:
	.def	___main;	.scl	2;	.type	32;	.endef
.text
LC0:
	.ascii "%d\0"
	.align 4
.globl _main
	.def	_main;	.scl	2;	.type	32;	.endef
_main:
	pushl %ebp
	movl %esp,%ebp
	subl $20,%esp
	pushl %ebx
	movl 8(%ebp),%ebx
	call ___main
	imull $12345,%ebx,%ebx
	addl $-8,%esp
	movl $6,%eax
	testb $1,%bl
	je L3
	movl $5,%eax
L3:
	pushl %eax
	pushl $LC0
	call _printf
	movl -24(%ebp),%ebx
	movl %ebp,%esp
	popl %ebp
	ret
	.def	_printf;	.scl	2;	.type	32;	.endef

Чтобы не мучиться в поисках отличий, запускаем:

Код:
diff test1.s test2.s
Получаем:

Код:
1c1
<       .file   "test1.c"
---
>       .file   "test2.c"
 

whirlwind

TDD infected, paranoid
Crazy ты не хитри ;) про тернарный ? никто тут не говорил. Даже VC его умудрился более менее нормально скомпилировать

Код:
9:        printf("%d", (x & 1) ? 5 : 6);
0040D694   mov         eax,dword ptr [ebp-4]
0040D697   and         eax,1
0040D69A   neg         eax
0040D69C   sbb         eax,eax
0040D69E   add         eax,6
0040D6A1   push        eax
0040D6A2   push        offset string "%d" (0042201c)
0040D6A7   call        printf (00401070)
0040D6AC   add         esp,8
Код:
9:        printf("%d", (x % 2 != 0) ? 5 : 6);
0040D694   mov         eax,dword ptr [ebp-4]
0040D697   and         eax,80000001h
0040D69C   jns         main+33h (0040d6a3)
0040D69E   dec         eax
0040D69F   or          eax,0FFFFFFFEh
0040D6A2   inc         eax
0040D6A3   neg         eax
0040D6A5   sbb         eax,eax
0040D6A7   add         eax,6
0040D6AA   push        eax
0040D6AB   push        offset string "%d" (0042201c)
0040D6B0   call        printf (00401070)
0040D6B5   add         esp,8
давай вариант с if и желательно поменьше лишнего ассемблера

PS. В любом случае, уже приведенных примеров достаточно что бы выбрать в пользу логических операций - мало ли каким компилятором будет собираться программа.
 

440hz

php.ru
спасибо, парни ... с таким удовольствием читаю ... (утирая скупую слезу)

давате еще обсудим $i++ и ++$i и их реализацию на с, с++ и php ? там то же есть много интересного и поучительного.
 

Crazy

Developer
Автор оригинала: whirlwind
Crazy ты не хитри ;) про тернарный ? никто тут не говорил.
Не вопрос. Возьмем test1.c:

Код:
int main (int argc, char** argv) {
  int x = argc * 12345;
  int y;
  if (x & 1) y = 5; else y = 6;
  printf("%d", y);
}
...и test2.c:


Код:
int main (int argc, char** argv) {
  int x = argc * 12345;
  int y;
  if (x % 2 != 0) y = 5; else y = 6;
  printf("%d", y);
}
Сразу посмолтрим diff:

Код:
1c1
<       .file   "test1.c"
---
>       .file   "test2.c"
Поскольку файлы кроме этой строки не различаются, публикую только test1.s:

Код:
	.file	"test1.c"
gcc2_compiled.:
___gnu_compiled_c:
	.def	___main;	.scl	2;	.type	32;	.endef
.text
LC0:
	.ascii "%d\0"
	.align 4
.globl _main
	.def	_main;	.scl	2;	.type	32;	.endef
_main:
	pushl %ebp
	movl %esp,%ebp
	subl $20,%esp
	pushl %ebx
	movl 8(%ebp),%ebx
	call ___main
	imull $12345,%ebx,%ebx
	movl $6,%eax
	testb $1,%bl
	je L3
	movl $5,%eax
L3:
	addl $-8,%esp
	pushl %eax
	pushl $LC0
	call _printf
	movl -24(%ebp),%ebx
	movl %ebp,%esp
	popl %ebp
	ret
	.def	_printf;	.scl	2;	.type	32;	.endef
P.S. Не знал, что у VC так плохо с оптимизацией. Век живи -- век учись...

-~{}~ 31.08.06 17:41:

Автор оригинала: 440hz
давате еще обсудим $i++ и ++$i и их реализацию на с, с++ и php ? там то же есть много интересного и поучительного.
Ой... лучше не надо. У меня, как у человека с тяжелым детством (игрушечный C на деревянной CM-4, прибитой к полу), до сих пор трудноизлечимая привычка писать в for'е строго ++i, а не i++. Долго лечился, но до сих пор бывают рецедивы. :)
 

whirlwind

TDD infected, paranoid
хм... у мну на рядовой тачке ваще вон че получилось

Код:
	.file	"main1.c"
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC0:
	.string	"%d"
	.text
	.p2align 2,,3
.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$8, %esp
	movl	8(%ebp), %eax
	andl	$-16, %esp
	andl	$1, %eax
	subl	$24, %esp
	cmpl	$1, %eax
	sbbl	%eax, %eax
	notl	%eax
	addl	$6, %eax
	pushl	%eax
	pushl	$.LC0
	call	printf
	leave
	ret
	.size	main, .-main
 

Vladson

Сильнобухер
Автор оригинала: 440hz
давате еще обсудим $i++ и ++$i и их реализацию на с, с++ и php ? там то же есть много интересного и поучительного.
Давайте обсудим, и не обязательно $i++ можнл много другой интересной информации обсудить, приятно читать как все друг другу одно и тоже доказывают (что технически нет разницы) и каждый считает что только он прав
 

phprus

Moderator
Команда форума
Crazy
Так. Я не думал, что gcc в отличие от VS оптимизирует x%2 до x&1.

440hz
спасибо, парни ... с таким удовольствием читаю ... (утирая скупую слезу)
Не за что.

давате еще обсудим $i++ и ++$i и их реализацию на с, с++ и php ? там то же есть много интересного и поучительного.
А что. Можно пообсуждать. :)
 

dr-sm

Новичок
мощщно...
phprus +1
if ($i & 1) или if ($i % 2) выглядит более красиво, а руки яб отрывал за непроставленные скобки.

Crazy гонишь неподеццки ).

давай лучше такой вот случай рассмотрим:

if (stuff *s = this_function_may_return_null()) {
return s->is_odd();
}

это что, тоже менее читабельно получается?
 

Solid

Drosera anglica
Если уж и сравнивать, то сравнивать правильно (если уж на то пошло дело):
PHP:
var_dump(is_even_number(5));
var_dump(is_even_number(4));
var_dump(is_even_number(4.5));
var_dump(is_even_number(3.5));

function is_even_number($number) {
   if($number%2===0) {
      return true;
   } else {
      return false;
   }
}
Хотя мне всётаки близок вариант if($number%2), т.к. мы программируем не на C, и даже не на C++, и даже не на C# или Java. Мы, дорогие господа, программируем на PHP. А у PHP, в отличии от всех выше перечисленных языков есть один большой плюс - лаконичность. А как поговаривал великий Антон Павлович - "Краткость сестра таланта". Так что давайте будем талантливыми и не будем устраивать лишнюю демагогию, коию устроили вы здесь.

PS. Насчёт C/C++ компиляторов которые вы здесь использовали... так всё очень просто. В наши времена компиляторы не такие уж и идиоты, что бы линковать и ассемблировать код без оптимизации. Так что, прошу вас, ну не надо... давайте лучше по существу.

PPS. Быстрее всего работает (причём берёт как int, так и float и string:
PHP:
function is_even_number($number) {
	if($number&1) {
		return false;
	} else {
		return true;
	}
}
 

Crazy

Developer
Автор оригинала: dr-sm
давай лучше такой вот случай рассмотрим:

if (stuff *s = this_function_may_return_null()) {
return s->is_odd();
}

это что, тоже менее читабельно получается?
Еще один любитель спорить сам с собой. Менее читабельно по сравнению с чем?
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху