Страницы: 1
RSS
СУММПРОИЗВ и двойное бинарное отрицание (продолжение)
 
поскольку решение задачи было найдено сразу же и настолько красиво сделано, то обсуждение в той теме сразу же вильнуло в сторону.  
посему решил вытащить интересность в отдельную ветку.  
исходная тема:  
http://www.planetaexcel.ru/forum.php?thread_id=5516  
 
А начали обсуждать там вот эту формулу:  
 
=СУММПРОИЗВ(--(ДЕНЬНЕД(ДАТА(A2;B2;СТРОКА($A$1:$A$7));2)=3); ДАТА(A2;B2;СТРОКА($A$1:$A$7)) )  
 
вот другие варианты формул, выполняющих те же задачи:  
 
формула без двойного бинарного отрицания  
=СУММПРОИЗВ((ДЕНЬНЕД(ДАТА(A2;B2;СТРОКА($A$1:$A$7));2)=3)*ДАТА(A2;B2;СТРОКА($A$1:$A$7)))  
 
формула массива  
=МИН(ЕСЛИ(ДЕНЬНЕД(ДАТА(A2;B2;СТРОКА(A1:A7));2)=3;ДАТА(A2;B2;СТРОКА(A1:A7))))  
 
некоторые объяснения по теме:  
- Первый минус означает приоритет выполнения функции, а так как дата не может быть отрицательна нужен второй минус...    
(Sh_Alex)  
 
- На сколько мне известно "двойное отрицание" (--) переводит ИСТИНА в 1, а ЛОЖЬ в 0. Таким образом, например, =СУММ(ИСТИНА,ЛОЖЬ,ИСТИНА) даст ошибку, а вот =СУММ(1,0,1) спокойно посчитается и будет ответ 2. (Pavel55)  
 
- Не только двойное отрицание, но пресловутое умножение на единицу дает то же самое, т.е. ИСТИНА -> 1  
Аналогично, сложение с нулем. (Лузер™)  
 
Соответственно, рождаются и другие вопросы по теме. Давайте будем задавать их тут, тут же и порешаем.
 
А что приемы никто не читает?  
http://www.planetaexcel.ru/tip.php?aid=94
 
неопределенный мсье видимо только тему прочитал?  
за ссылку спасибо, пусть будет на виду...  
кстати, в исходной теме ZVI дал еще кое-какие разъяснения.
 
Тут наткнулся на приемчики и хотел бы узнать, где и куда нужно отрицания вставлять, чтобы из закрытого файла брались данные?  
 
=СМЕЩ('\\Domain.local\ldocs\TS\[!!Списки 2010-2011.xlsm]п.л.'!$B1;ВПР(номеркласса;inf!$A$2:$C$15;3;0)-1;0)
 
Спасибо
 
В столбце С должны быть числовые данные. Если там число в текстовом формате, то    
--ВПР(...)  
Лучше кусочек примера из рабочего файла, избавимся от летучего СМЕЩ.
 
Высылаю фрагмент файлов.  
Спасибо.  
<EM><STRONG>Файл удален</STRONG> - велик размер - [<STRONG>МОДЕРАТОРЫ</STRONG>]</EM>
 
Здесь так не играют. Читайте:  
http://www.planetaexcel.ru/forum.php?thread_id=8735
 
двойное бинарное отрицание - это краснословие :)  
 
так как такого оператора в vba нет, то оно его считает за два унарных отрицания(унарных - в смысле один операнд(для тех кто понимает в извращениях)(вот почти как я тут двойные скобки применяю)).. оппс.. уже тройные :)  
 
 
ну а дальше.. скучища. кому это надо?  унарное отрицание определено для числовых значений.. т.е. собственно числовые значения различной природы и точности, а так же дата/время и логические. При всем при этом результатом будет "число"(так уж задумано). При необходимости проводятся преобразования операнда  - логические значения при этом преобразуются в числа. причем в иксель это происходит отлично от vba  (ну или наоборот).  
 
в иксель -истина=-1; -ложь=0  
 
vba    -true=1;  -false=0  
 
второе отрицание применяется уже к получившемуся числу, поэтому преобразования тут не требуется, просто меняется знак числа.  
 
аналогичные преобразоания производятся при применении любых арифметических операторов  
 
вот что быстрее  - два раза поменять знак или сложить с нулем я не знаю..  
 
 
подозреваю, что поменять знак..
Живи и дай жить..
 
попробовал в vba - разницы в скорости нет.
Живи и дай жить..
 
{quote}{login=слэн}{date=01.12.2010 03:02}{thema=}{post}попробовал в vba - разницы в скорости нет.{/post}{/quote}  
 
а между  
=ЕСЛИ(не(НЕ(ИСТИНА));1;0)  
и  
=ЕСЛИ(--(ИСТИНА);1;0)  
и  
=ЕСЛИ(--1;1;0)  
А?
 
a = True + 0  
 
на 40% быстрее, чем  
 
a = Not Not True  
 
 
кроме того, что разные значения в результате
Живи и дай жить..
 
a=--1  также, как и a=true+0
Живи и дай жить..
 
Добрый вечер всем!  
Вроде о формулах была речь, сравните:  
 
Sub Test()  
   
 Const N& = 100  
 Dim t!, i, Rng1 As Range, Rng2 As Range  
   
 Set Rng1 = Columns(1)  
 Set Rng2 = Columns(1)  
 Rng1.Formula = "=-(TRUE)"  
 Rng2.Formula = "=TRUE+0"  
   
 With Application  
   .EnableEvents = False  
   .ScreenUpdating = False  
   .Calculation = xlCalculationManual  
 End With  
   
 t = Timer  
 For i = 1 To N  
   Rng1.Formula = "=--TRUE"  
 Next  
 t = Timer - t  
 Debug.Print 1, Round(t, 3)  
   
 t = Timer  
 For i = 1 To N  
   Rng2.Formula = "=TRUE+0"  
 Next  
 t = Timer - t  
 Debug.Print 2, Round(t, 3)  
   
 With Application  
   .Calculation = xlCalculationAutomatic  
   .EnableEvents = True  
   .ScreenUpdating = True  
 End With  
   
End Sub
 
Но чаще всего отличие во временах несущественно и зависит от условий тестирования.  
Несложно получить и противоположный результат, например, сравнивая не время записи формул, а пересчет ранее записанных формул, т.е Rng1.Calculate и Rng2.Calculate  :-)
 
Исправил опечатку, все-таки двойное отрицание быстрее.  
Когда-то я уже предлагал убедиться, что excel в формулах двойное отрицание выполняет за одно действие, а не за 2: на ячейке с формулой =--ИСТИНА, меню Сервис - Зависимости форимул - Вычислить формуул - Вычислить.  
   
Sub Test()  
   
 Const N& = 100  
 Dim t!, i&, Rng1 As Range, Rng2 As Range  
   
 Set Rng1 = Columns(1)  
 Set Rng2 = Columns(2)  
 Rng1.Formula = "=--TRUE"  
 Rng2.Formula = "=TRUE+0"  
   
 With Application  
   .EnableEvents = False  
   .ScreenUpdating = False  
   .Calculation = xlCalculationManual  
 End With  
   
 t = Timer  
 For i = 1 To N  
   'Rng1.Formula = "=--TRUE"  
   Rng1.Calculate  
 Next  
 t = Timer - t  
 Debug.Print 1, Round(t, 3)  
   
 t = Timer  
 For i = 1 To N  
   'Rng2.Formula = "=TRUE+0"  
   Rng2.Calculate  
 Next  
 t = Timer - t  
 Debug.Print 2, Round(t, 3)  
   
 With Application  
   .Calculation = xlCalculationAutomatic  
   .EnableEvents = True  
   .ScreenUpdating = True  
 End With  
   
End Sub
 
Нет, всё таки два отрицания - это два отрицания, а не одно :-)  
 
Private Sub CommandButton1_Click()  
Dim t#, tmp1, tmp2, i  
t = Timer  
For i = 1 To 100  
tmp1 = [-ROW(A1:IV65536)]
Next  
[a1] = Timer - t
 
t = Timer  
For i = 1 To 100  
tmp2 = [--ROW(A1:IV65536)]
Next  
[a2] = Timer - t
End Sub  
 
Поэтому иногда имеет смысл в формулах массива один минус выносить за пределы перебора, например: =-СУММ(-ЕСЛИ(условие;выраж1;выраж2))
 
{quote}{login=@Nik}{date=01.12.2010 06:46}{thema=}{post}Нет, всё таки два отрицания - это два отрицания, а не одно :-){/post}{/quote}Насколько я понимаю, двойное бинарное отрицание это специфическая орперация, а не две операции отрицания :-)  
Никто не утверждал, что операция обычного отрицания медленнее операции двойного бинарного. Если уж сравнивать два отрицания с двойным бинарным, тогда так:  
 
Sub Test1()  
 
 Const N& = 100  
 Dim t!, i&, Rng1 As Range, Rng2 As Range  
 
 Set Rng1 = Columns(1)  
 Set Rng2 = Columns(2)  
 Rng1.Formula = "=--TRUE"  
 Rng2.Formula = "=-(-TRUE)"  
 
 With Application  
   .EnableEvents = False  
   .ScreenUpdating = False  
   .Calculation = xlCalculationManual  
 End With  
 
 t = Timer  
 For i = 1 To N  
   Rng1.Calculate  
 Next  
 t = Timer - t  
 Debug.Print 1, Round(t, 3)  
 
 t = Timer  
 For i = 1 To N  
   Rng2.Calculate  
 Next  
 t = Timer - t  
 Debug.Print 2, Round(t, 3)  
 
 With Application  
   .Calculation = xlCalculationAutomatic  
   .EnableEvents = True  
   .ScreenUpdating = True  
 End With  
 
End Sub
 
ZVI, ну вы то уж повторяете вырвавшееся у кого-то выражение.  
 
оно же не имеет смысла - двойное бинарное...  
 
операторы бывают унарные - с одним операндом, и бинарными - с двумя..  
 
отрицание - унарный оператор.  
 
дайте ссылку на определение двойного отрицания, по крайней мере..
Живи и дай жить..
 
Я, всё таки, считаю, что подобные тесты нужно проводить на формулах массива. Посему вот мой вариант теста, где видно, что --(...) немного отстаёт от -(-(...)). Но разница настолько мала по сравнению со временем вычисления других функций, что ею можно принебречь и не заморачиваться с синтаксисом.  
 
Private Sub CommandButton1_Click()  
[A2].FormulaArray = "=-SUM(-(ROW(A1:A65536)>0))"
[B2].FormulaArray = "=SUM(--(ROW(B1:B65536)>0))"
End Sub  
 
Private Sub CommandButton2_Click()  
Dim t!, i&, N&  
N = 50  
t = Timer  
For i = 1 To N  
 [a2].Dirty
Next  
t = Timer - t  
[a1] = Round(t, 3)
 
t = Timer  
For i = 1 To N  
 [b2].Dirty
Next  
t = Timer - t  
[b1] = Round(t, 3)
End Sub
 
а суммпроизв все равно рулит
 
Слэн, конечно же правильно говорить двойное унарное отрицание.  
Бинарное отрицание тоже бывает, но это другоя тема :-)  
И о том, и о другом здесь: http://www.planetaexcel.ru/forum.php?thread_id=14194  
 
@Nik - согласен с Вами, что разумнее действовать по ситуации и предпочтениям.  
 
Кстати о предпочтениях, Harlan Grove так описал причину предпочтения двойного унарного оператора отрицания другим, таким как умножению на единицу, сложение с нулём и т.п.  
 
".... it's not the speed of double unary minuses I like, it's the fact that due to Excel's operator precedence it's harder to screw up double unary minuses with typos than it is to screw up the alternatives ^1, *1, +0. Also, since I read left to right, I prefer my number type coercions on the left rather than the right of my Boolean expressions, and -- looks nicer than 1* or 0+. Wrapping Boolean expressions inside N() is another alternative, possibly clearer, but it eats a nested function call level, so I don't use it."  
 
Вольный перевод:  
"...Я люблю не скорость оператора двойного отрицания, а то, что в таком операторе труднее сделать синтаксическую ошибку по сравнению с альтернативными ^1, *1, +0. И так как я читаю слева направо, то предпочитаю, чтобы операция преобразования логических значений в числовые была слева (видна сразу), а не справа от логических выражений. Да и -- выглядит лучше, чем 1* или 0+. Преобразование логических выражений в числовые с помощью функции Ч(ЛогВыражение) – еще одна альтернатива, возможно более понятная, но это увеличивает уровень вложенности функций, поэтому я не использую такой вариант"
 
вот к нему не придерешься - "double minuses" и ни слова про оператор :)  
 
 
пусть всем будет понятно, что это не оператор, а два оператора.  
 
вот в си есть оператор "--", даже два..  но оба унарные - лево- и правосторонние - какой ужас :)
Живи и дай жить..
 
to @Nik - вот именно, про это я и начинал..
Живи и дай жить..
 
{quote}{login=vikttur}{date=01.12.2010 01:43}{thema=}{post}Здесь так не играют. Читайте:  
http://www.planetaexcel.ru/forum.php?thread_id=8735{/post}{/quote}  
 
Виноват! Но пришлось слишком много урезать:)
 
{quote}{login=shalun}{date=03.12.2010 05:00}{thema=Re: }{post}Виноват! Но пришлось слишком много урезать:){/post}{/quote}  
1. Что с этим делать?  
2. shalun=Андрей?
Страницы: 1
Читают тему
Наверх