Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
x^=y^=x^=y (для тех кто в танке, это хитро записанный обмен значений x и y)Примерно как x^=y^=x^=y (для тех кто в танке, это хитро записанный обмен значений x и y)
XOR x,y; XOR y,x; XOR x,y уже нечего оптимизировать, но JVM на нормальные процессоры не похожа. Получается жутковатый байткод с кучей копирований:
6: iload_1
7: iload_2
8: iload_1
9: iload_2
10: ixor
11: dup
12: istore_1
13: ixor
14: dup
15: istore_2
16: ixor
17: istore_1
любой вариант обмена значениями без использования третьей "ячейки" некорректен: представьте, что для обмена передали одно и то же значение.Вариант x ^= y; y ^= x; x ^= y; работает корректно даже если x == y, представьте себе. А вариант x^=y^=x^=y; является некорректным с точки зрения С++ потому, что переменная изменяется более одного раза между двумя точками следования.
void swap(int&, int&);
void swap(int& x, int&y)
{
x ^= y;
y ^= x;
x ^= y;
}
void swap(int& x, int& y)
{
if (x == y) return;
x ^= y;
y ^= x;
x ^= y;
}
BSD стиль:
function x()
{
//operator
}
GNU стиль:
function x()
{
//operator
}
K&R стиль:
function x(){
//operator
}
| mov | edx,esi | ||
| shr | edx,1 | ||
| and | edx,055555555h | ; (n >> 1) & 0x55555555 | |
| sub | esi,edx | ; n - ((n >> 1) & 0x55555555) | |
| mov | edx,esi | ||
| shr | edx,2 | ; n >> 2 | |
| and | esi,033333333h | ; n & 0x33333333 | |
| and | edx,033333333h | ; (n >> 2) & 0x33333333 | |
| add | esi,edx | ; n = (n & 0x33333333) + ((n >> 2) & 0x33333333) | |
| mov | edx,esi | ||
| shr | edx,4 | ; n >> 4 | |
| add | edx,esi | ; n + (n >> 4) | |
| and | edx,00F0F0F0Fh | ; n = (n + (n >> 4) & 0x0F0F0F0F) | |
| imul | edx,001010101h | ; add by multiplying with a "magic number" | |
| shr | edx,24 | ; shift result into place |
/*
code1
/*/
code2
//*/
++++++++++[>+++++++>++++++++++>+++++++++++<<<-]>++.>---.+.>++++<-.<.>-.+.>.>.
#!/usr/bin/perl
use warnings;
use strict;
use Benchmark qw(:all);
sub get_ones_bitwise {
my ($x) = @_;
$x = ($x & 0x55555555) + (($x & 0xAAAAAAAA) >> 1);
$x = ($x & 0x33333333) + (($x & 0xCCCCCCCC) >> 2);
$x = ($x & 0x0F0F0F0F) + (($x & 0xF0F0F0F0) >> 4);
$x = ($x & 0x00FF00FF) + (($x & 0xFF00FF00) >> 8);
$x = ($x & 0x0000FFFF) + (($x & 0xFFFF0000) >> 16);
return $x;
}
sub get_ones_tr {
return sprintf("%016b", shift)=~tr/1//;
}
sub get_ones_unpack {
return unpack "%32b*", pack "L", shift;
}
our @test = (0,1,3,255,256,1023,1024,0x33333333,0xFFFF0000,0xFFFFFFFF);
@test = (@test) x 100;
cmpthese(1000, {
bitwise => sub { get_ones_bitwise($_) for @test },
unpack => sub { get_ones_unpack($_) for @test },
tr => sub { get_ones_tr($_) for @test },
});
__END__
Rate bitwise unpack tr
bitwise 532/s -- -44% -45%
unpack 952/s 79% -- -2%
tr 971/s 83% 2% --
Вот так. Самый быстрый-то, оказывается, tr - которому сам Ларри Уолл велел считать кол-во одинаковых символов в строке. :)
Jaguar
sysprg
sysprg
Rate while2 while bitwise bitwise2 unpack tr
while2 249/s -- -3% -52% -55% -73% -74%
while 258/s 4% -- -51% -53% -72% -73%
bitwise 524/s 110% 103% -- -5% -44% -46%
bitwise2 549/s 120% 113% 5% -- -41% -43%
unpack 935/s 275% 262% 79% 70% -- -3%
tr 962/s 286% 272% 84% 75% 3% --
Красив ли код???