поскольку решение задачи было найдено сразу же и настолько красиво сделано, то обсуждение в той теме сразу же вильнуло в сторону. посему решил вытащить интересность в отдельную ветку. исходная тема: 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;СТРОКА(A1:A7));2)=3;ДАТА(A2;B2;СТРОКА(A1:A7))))
некоторые объяснения по теме: - Первый минус означает приоритет выполнения функции, а так как дата не может быть отрицательна нужен второй минус... (Sh_Alex)
- На сколько мне известно "двойное отрицание" (--) переводит ИСТИНА в 1, а ЛОЖЬ в 0. Таким образом, например, =СУММ(ИСТИНА,ЛОЖЬ,ИСТИНА) даст ошибку, а вот =СУММ(1,0,1) спокойно посчитается и будет ответ 2. (Pavel55)
- Не только двойное отрицание, но пресловутое умножение на единицу дает то же самое, т.е. ИСТИНА -> 1 Аналогично, сложение с нулем. (Лузер™)
Соответственно, рождаются и другие вопросы по теме. Давайте будем задавать их тут, тут же и порешаем.
В столбце С должны быть числовые данные. Если там число в текстовом формате, то --ВПР(...) Лучше кусочек примера из рабочего файла, избавимся от летучего СМЕЩ.
так как такого оператора в vba нет, то оно его считает за два унарных отрицания(унарных - в смысле один операнд(для тех кто понимает в извращениях)(вот почти как я тут двойные скобки применяю)).. оппс.. уже тройные :)
ну а дальше.. скучища. кому это надо? унарное отрицание определено для числовых значений.. т.е. собственно числовые значения различной природы и точности, а так же дата/время и логические. При всем при этом результатом будет "число"(так уж задумано). При необходимости проводятся преобразования операнда - логические значения при этом преобразуются в числа. причем в иксель это происходит отлично от vba (ну или наоборот).
в иксель -истина=-1; -ложь=0
vba -true=1; -false=0
второе отрицание применяется уже к получившемуся числу, поэтому преобразования тут не требуется, просто меняется знак числа.
аналогичные преобразоания производятся при применении любых арифметических операторов
вот что быстрее - два раза поменять знак или сложить с нулем я не знаю..
Но чаще всего отличие во временах несущественно и зависит от условий тестирования. Несложно получить и противоположный результат, например, сравнивая не время записи формул, а пересчет ранее записанных формул, т.е 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
{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
Я, всё таки, считаю, что подобные тесты нужно проводить на формулах массива. Посему вот мой вариант теста, где видно, что --(...) немного отстаёт от -(-(...)). Но разница настолько мала по сравнению со временем вычисления других функций, что ею можно принебречь и не заморачиваться с синтаксисом.
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
@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+. Преобразование логических выражений в числовые с помощью функции Ч(ЛогВыражение) – еще одна альтернатива, возможно более понятная, но это увеличивает уровень вложенности функций, поэтому я не использую такой вариант"
{quote}{login=shalun}{date=03.12.2010 05:00}{thema=Re: }{post}Виноват! Но пришлось слишком много урезать:){/post}{/quote} 1. Что с этим делать? 2. shalun=Андрей?