Задачка закачка Булева променлива.. масив.. :)

ThinkFast

New Member
Имаш булева променлива $exist
Имаш масив $result = array(1=>'Намерено', 2=>'Ненамерено');

Логиката е:
Ако $exist е True, трябва да изкараш на екрана 'Намерено',
Ако $exist e False, трябва да изкараш на екрана 'Ненамерено'.

Как би го направил?
 
От: Нов програмист си търси работа :)

@ThinkFast много ми е интересно ти какво предлагаш. надявам се накрая да покажеш твоето решение. защото на така зададения масив това ми се вижда и на мен оптималният вариант.
 
Последно редактирано:
От: Нов програмист си търси работа :)

Може така:

echo $result[2 - $exist];

или ако искаш така:

echo $result[($exist ^ 1) + 1];

:)
 
От: Нов програмист си търси работа :)

Може така:

echo $result[2 - $exist];

или ако искаш така:

echo $result[($exist ^ 1) + 1];

:)

:D
Е аз бих го написал така:
echo $result[2-(integer)$exist]
или
echo $result[1+(integer)(!$exist)]

за изключващото или не се сетих
 
От: Нов програмист си търси работа :)

извинявам се колеги, но всичките ви варианти са по бавни от първия гарантирано, въпреки , че вие си мислите че са по бързи щом са по кратко написани, но нешата са различни.

Да оценим постъпково какво се случва :
$e = ($exist) ? $result[1] : $result[2];
echo $e;

стъпка 1 : да /не (много бързо)
стъпка 2 : взима точно определен индекс (няма адресна аритеметика много бързо)

===========================
echo $result[2 - $exist];
тука както става :

1. $exist го каства до (int)
2. от 2 вади $exist
3. смята кой е елемента
4. проблем с логиката, може да няма такъв елемент

================
echo $result[($exist ^ 1) + 1];

тука е още по зле

1. exist го прави (int)
2. увеличава побитово с 1 (това е най бързо, в случая не добре)
3. събира го с 1
4. смята кой е адреса
5. проблем с логиката, може да няма такъв елемент

================

не знам момчета, може и да не размишлявам правилно, но за бързина бих заложил на вариант 1. а за да е още по секси бих си сложил индексите 0 и 1.
 
От: Нов програмист си търси работа :)

Не съм се замисял как ще е по-бързо. По-принцип бих го написал точно като теб при така зададено условие. А за най-секси - побитовото, изглежда като писано от някой гуру :)

В този вариант защо не си добавил точка "проблем с логиката, може да няма такъв елемент" ?
 
От: Нов програмист си търси работа :)

@bobbydigital
Не съм съгласен с теб.
За да не спорим пусни си ей това скриптче:
Код:
<?
$result = array(1=>'Exist', 2=>'Not exist');
$exist = false;
$cycles = 5000000;

$dt1 = microtime(true);
for ($i=0; $i<$cycles; $i++) {
  $rslt = $result[2-(integer)$exist];
}
$dt1 = microtime(true)-$dt1;

$dt2 = microtime(true);
for ($i=0; $i<$cycles; $i++) {
  $rslt = $result[1+(integer)(!$exist)];
}
$dt2 = microtime(true)-$dt2;

$dt3 = microtime(true);
for ($i=0; $i<$cycles; $i++) {
  $rslt = $result[1 + (integer)($exist) ^ 1];
}
$dt3 = microtime(true)-$dt3;

$dt4 = microtime(true);
for ($i=0; $i<$cycles; $i++) {
  $rslt = ($exist) ? $result[1] : $result[2];
}
$dt4 = microtime(true)-$dt4;

echo "$dt1<br>$dt2<br>$dt3<br>$dt4";

?>
Това е резултатът който даде при мен:
0.719979047775
0.886523962021
2.09785199165
0.814927101135

Предполагах че XOR-а ще се забави, но чак пък толкова... :shock:


А, и какво ще рече "проблем с лоигката, може да няма такъв елемент" ???
typecast-a със сигурност ще върне 1 или 0, масивът е "даден", какво според теб може да се обърка?
Защо си мислиш че кастването отнема време? То е просто различен достъп до паметта, а не операция.
А това "да/не - много бързо" не е толкова бързо защото се извършва сравнение!
IF като време е > (+/-) като време. // Става дума за integer променливи.
"увеличава побитово с 1 (това е най бързо, в случая не добре)" - Защо си мислиш че е побитово увеличаване. Такава операция няма. Това е XOR и поради спецификата на операцията предполагах че ще е по бавно.



Моля някой модератор да премести тези постове в някоя тема като "PHP Speed", че тука осрахме темата на човека.
 
Последно редактирано:
От: Нов програмист си търси работа :)

пуснак скрипта и ми заби всичко. това значи че тече памет от някъде.

@ThinkFast

смени $exist = true; и виж какво ще рече "проблем с логиката, може да няма такъв елемент". по принцип така съм възпитам винаги да проверявам за да не става омазване.

Защо си мислиш че кастването отнема време?
защото се заделя памет за нова временна променлива от новият тип към които кастваш.

А това "да/не - много бързо" не е толкова бързо защото се извършва сравнение!

много е бързо , защото компилатора знае стойността на променливата по време на компилация, докато при другите варианти се прави runtime.

IF като време е > (+/-) като време. // Става дума за integer променливи. по принцип може би, но в случая не.

на мен това ми дава като резултати при false :

PHP:
Notice:  Undefined offset:  0 in D:\www\myads\htdocs\t.php on line 20

Notice:  Undefined offset:  0 in D:\www\myads\htdocs\t.php on line 20

Notice:  Undefined offset:  0 in D:\www\myads\htdocs\t.php on line 20

Notice:  Undefined offset:  0 in D:\www\myads\htdocs\t.php on line 20

Notice:  Undefined offset:  0 in D:\www\myads\htdocs\t.php on line 20
2.0027160644531E-5
7.1525573730469E-6
0.00060582160949707
1.0013580322266E-5

и това при false :

PHP:
Notice:  Undefined offset:  3 in D:\www\myads\htdocs\t.php on line 20

Notice:  Undefined offset:  3 in D:\www\myads\htdocs\t.php on line 20

Notice:  Undefined offset:  3 in D:\www\myads\htdocs\t.php on line 20

Notice:  Undefined offset:  3 in D:\www\myads\htdocs\t.php on line 20

Notice:  Undefined offset:  3 in D:\www\myads\htdocs\t.php on line 20
1.7881393432617E-5
7.1525573730469E-6
0.0006558895111084
1.0013580322266E-5


@vaskoa - съжелявам но не те разбрах какво ми казваш.

p.s. момчета и за да не си помислите, че се заяждам, го казвам ясно, не се заяждам, просто ми стана интересна темата. за мен най - чист и обоснован си остава първият вариант.

п.с. без лоши чувства
 
От: Нов програмист си търси работа :)

Ето и резултатите при мен:

при TRUE
---------------
1.93693304062
2.07864809036
8.69399189949
2.58300495148
2.60089898109
1.68554997444

при FALSE
---------------
1.98906683922
2.09804081917
8.89155387878
2.67043304443
2.6078350544
1.69114208221

Последните два резултата са от тоя код:

Код:
$dt5 = microtime(true);
for ($i=0; $i<$cycles; $i++) 
{
	switch($exist)
	{
		case 0:$rslt = $result[1];
		break;
		case 1:$rslt = $result[2];
		break;
	}
}
$dt5 = microtime(true)-$dt5;

$dt6 = microtime(true);
for ($i=0; $i<$cycles; $i++) 
{
	if($exist) {$rslt = $result[1];}
	else {$rslt = $result[2];}
}
$dt6 = microtime(true)-$dt6;

което при моите тестове показва, че доброто старо писане с IF и ELSE дава най-добри резултати :)
 
От: Нов програмист си търси работа :)

bobbydigital
Човек сложи си читава версия на PHP. Парсера му е омацан. Смята ти първо събирането после XOR-a. Това е 100% бъг в PHP версията ти.
Глупаво е в логиката която съм написал да предвиждам бъгове от страна на PHP.
Точно поради този бъг ти дава индекси 0 и 3 и от там гърми. Което е причина да ти дава най малко време за тази операция. Което е предпоставка да сметна резултатите ти за невалидни.

Кастването не е такова каквото го мислиш. Имаш клетка в паметта където имаш запаметена стойност за булев тип. Представи си че имаш променлива от тип интегер на същото място в паметта и я четеш. Няма никаква разлика. (точно в PHP не съм на 100% сигурен че е реализирано по този начин)

За компилацията си прав, но само за компилацията. PHP е скриптов език и няма компилация. Имаме само парсване.

Shmitkata обаче вкара интересна статистика. Хмм

Едит: Предполагам IF-ELSE конструкцията в PHP е оптимизирана за булеви сравнения, докато ? : не е. Нямам друго логично обяснение.
Всъщност мисля че PHP кешира нещо. Има значение кой тест след кой се изпълнява.
Като цяло ми е загадка защо IF-ELSE бие по скорост. Ама имам по важни задачи в момента, иначе теста беше интересен и поучителен.
 
Последно редактирано:
От: Нов програмист си търси работа :)

Кастването не е такова каквото го мислиш. Имаш клетка в паметта където имаш запаметена стойност за булев тип. Представи си че имаш променлива от тип интегер на същото място в паметта и я четеш. Няма никаква разлика. (точно в PHP не съм на 100% сигурен че е реализирано по този начин)
виж сега типът boolen заема 1 байт в паметта, като го кастнеш към int не може променливата да сочи към същото място защото типът int заема 4 байта, следователно интерпретатора прави нова временна променлива и ползва нея за пресмятането от къде идва и забавянето.

За компилацията си прав, но само за компилацията. PHP е скриптов език и няма компилация. Имаме само парсване.
принципът е абсолютно същият.

Човек сложи си читава версия на PHP. Парсера му е омацан.
напълно е възможно макар че е малко вероятно според мен.

сложи това преди скрипта и пробвай с твоята версия и виж резултата :
PHP:
error_reporting(E_ALL);
ini_set('display_errors' , 'on');
В крайна сметка изводът е че с if или съкратената му версия и най - бързо. въпреки че за php това е малко образно казано защото като се натиска f5 резултатите са променливи.

Хубава дискусия се заформи. мисля че всички научихме по нещо.
Съжелявам, че малко му наакахме темата на момчето.

п.с. без лоши чувства към всички.
п.с. 1
а така бих го направил аз ако не мога да пипам началния масив :
PHP:
$dt5 = microtime(true);
for ($i=0; $i<$cycles; $i++) {
      $rslt = $result[2];
      if($exist){
          $rslt = $result[1];
      }
}
$dt5 = microtime(true)-$dt5;
 
Последно редактирано:
От: Нов програмист си търси работа :)

Интересно се получи наистина, но по ми е интересно на какъв език пишеш по принцип? Сигурно C++
Ако си мислиш че тип bool заема 1 байт а int е 4 - много се лъжеш.
В PHP нещата са доста различни.
Затова казвам че не съм на 100% сигурен за някои неща като cast-ването.
Тука Zend са вкарали един базов тип: zval - мисля че беше 64 байта, или май 52. Не съм сигурен. Преди година и нещо се занимавах по сериозно с едни PHP extension-и и бая рових из ядрото на zend.
Та мисълта ми е, че bool и int са по еднакво байтове - колкото е структурата на zval.

Това за еррор-репортинга не е проблема. Виж си грешките - в единия случай имаше грешен индекс за масива: 0, а в другия - 3. Пресметни сметките без да се съобразяваш с приоритета на операциите и ще видиш че това е проблема при теб. Можеш да сложиш едни скоби на (integer)($exist) ^ 1 за да го изчисли първо него.

Разликата в компилацията и парсването е огромна. При компилацията в този случай ще ти сложи директни безусловни преходи и ще избегнеш проверките, докато тука дали знае или не знае стойността, задължително се проверява. Все пак компилацията включва в себе си оптимизация за процесора. Ако всеки път ще сравнява дали 1 е равно на 2, направо ще изключи проверката и директно ще премине към false блока, а true блока даже няма да се компилира. При парсването няма накъде да избягаш. Единствено можеш да кешираш.
И точно това ми се струва е причината IF-ELSE да бие по скорост. Кеширани данни. В една реална мултиюзър среда ме съмнява да е така.

Това последното направо не ми се тества вече. :)
ПП: Няма да е по бързо от IF-ELSE
В IF-ELSE имаш една проверка и едно присвояване
В твоя пример за TRUE имаш една проверка и две присвоявания
за FALSE имаш една проверка и едно присвояване
В общия случай губиш.
 
От: Задачка закачка Булева променлива.. масив.. :)

само да добавя още един аспект на програмирането: Четимост на Кода. По-добре го напишете така, че всеки да го разбира, а не на един ред всичко и да изглежда "гениално".
 
От: Задачка закачка Булева променлива.. масив.. :)

само да добавя още един аспект на програмирането: Четимост на Кода. По-добре го напишете така, че всеки да го разбира, а не на един ред всичко и да изглежда "гениално".


Безспорно, но аз останах с впечатлението, че само се забавляваме и обсъждаме варианти :)

Още една задачка? Какъв ще е резултата от този скрипт и защо?

<?php

error_reporting(E_ALL|E_STRICT);

$test = true;

$arr = array('ala','bala','nica');

echo in_array($test, $arr);

die;

?>
 
От: Задачка закачка Булева променлива.. масив.. :)

само да добавя още един аспект на програмирането: Четимост на Кода. По-добре го напишете така, че всеки да го разбира, а не на един ред всичко и да изглежда "гениално".

Съгласен съм. Но има много случаи когато трябва да оптимизираш независимо от четимостта на кода, понеже юзъра иска ефективност, него не му пука как е написан кода.
 
От: Задачка закачка Булева променлива.. масив.. :)

А защо не така: $result = array(1=>'Намерено', 0 =>'Ненамерено');

Останалото е лесно...
 
От: От: Задачка закачка Булева променлива.. масив.. :)

А защо не така: $result = array(1=>'Намерено', 0 =>'Ненамерено');

Останалото е лесно...
Защото програмирането не е лесно.
Представи си че масива е
$status = array(-1=> 'Operation not allowed', 0=>'Unknown', 1=>'Exist', 2=>'Not exist', 3=>'In use', 4=>'Forbidden', 5='Expired');
Ако промениш масива runtime, ще омацаш нещата.
 
От: От: Задачка закачка Булева променлива.. масив.. :)

....
Още една задачка? Какъв ще е резултата от този скрипт и защо?

$test = true;
$arr = array('ala','bala','nica');
echo in_array($test, $arr);

низ ? буул
има ли низ -> труе
1(труе)


Ся аз да питам, може ли квадрат да наследи кръг :D
 

Горе