Будет сдвиг разряда нулевыми битами работать правильно?

Вы пытались получить начальные миллисекунды, и после того, как событие было запущено, рассчитать разницу? вместо setTimeout. что-то вроде:

var startDate = new Date();
var startMilliseconds = startDate.getTime();

// when the event is fired :
(...), function() {
    console.log(new Date().getTime() - startMilliseconds);
});

старайтесь по возможности избегать использования jQuery. обычный JS даст вам лучшее время отклика и лучшую общую производительность

16
задан sharptooth 11 June 2009 в 12:23
поделиться

6 ответов

Очевидно , что по крайней мере один компилятор C ++ распознает ситуацию (когда 0 известен во время компиляции) и сделает ее запретной:

Источник

inline int shift( int what, int bitcount)
{
  return what >> bitcount ;
}

int f() {
  return shift(42,0);
}

Переключатели компилятора

icpc -S -O3 -mssse3 -fp-model fast=2 bitsh.C

Сборка Intel C ++ 11.0

# -- Begin  _Z1fv
# mark_begin;
       .align    16,0x90
        .globl _Z1fv
_Z1fv:
..B1.1:                         # Preds ..B1.0
        movl      $42, %eax                                     #7.10
        ret                                                     #7.10
        .align    16,0x90
                                # LOE
# mark_end;
        .type   _Z1fv,@function
        .size   _Z1fv,.-_Z1fv
        .data
# -- End  _Z1fv
        .data
        .section .note.GNU-stack, ""
# End

Как вы можете видеть на ..B1.1, Intel компилирует "return shift (42,0)" в "return 42".

Intel 11 также отбирает сдвиг для этих двух вариантов:

int g() {
  int a = 5;
  int b = 5;
  return shift(42,a-b);
}

int h(int k) {
  return shift(42,k*0);
}

Для случая, когда значение сдвига неизвестно во время компиляции ...

int egad(int m, int n) {
  return shift(42,m-n);
}

... сдвига нельзя избежать ...

# -- Begin  _Z4egadii
# mark_begin;
       .align    16,0x90
        .globl _Z4egadii
_Z4egadii:
# parameter 1: 4 + %esp
# parameter 2: 8 + %esp
..B1.1:                         # Preds ..B1.0
        movl      4(%esp), %ecx                                 #20.5
        subl      8(%esp), %ecx                                 #21.21
        movl      $42, %eax                                     #21.10
        shrl      %cl, %eax                                     #21.10
        ret                                                     #21.10
        .align    16,0x90
                                # LOE
# mark_end;

... но, по крайней мере, это встроен, поэтому нет накладных расходов на вызов.

Дополнительная сборка: volatile стоит дорого. Источник ...

int g() {
  int a = 5;
  volatile int b = 5;
  return shift(42,a-b);
}

... вместо того, чтобы не работать, компилируется в ...

..B3.1:                         # Preds ..B3.0
        pushl     %esi                                          #10.9
        movl      $5, (%esp)                                    #12.18
        movl      (%esp), %ecx                                  #13.21
        negl      %ecx                                          #13.21
        addl      $5, %ecx                                      #13.21
        movl      $42, %eax                                     #13.10
        shrl      %cl, %eax                                     #13.10
        popl      %ecx                                          #13.10
        ret                                                     #13.10
        .align    16,0x90
                                # LOE
# mark_end;

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

18
ответ дан 30 November 2019 в 15:24
поделиться

Он будет корректно работать на любой широко используемой архитектуре (могу поручиться за x86, PPC, ARM). Компилятор не сможет свести его к нулю, если функция не встроена.

4
ответ дан 30 November 2019 в 15:24
поделиться

Согласно K&R "Результат не определено, если правый операнд отрицательный, больше или равен количеству битов в типе левого выражения ". (A.7.8) Следовательно, >> 0 - это сдвиг вправо идентичности и совершенно законный.

28
ответ дан 30 November 2019 в 15:24
поделиться

Компилятор мог выполнить эту оптимизацию только в том случае, если бы он знал во время компиляции, что значение bitCount равно нулю. Это означало бы, что переданный параметр должен быть константой:

const int N = 0;
int x = shift( 123, N );

C ++, безусловно, допускает такую ​​оптимизацию, но мне неизвестны компиляторы, которые это делают. Альтернативный подход, который может использовать компилятор:

int x = n == 0 ? 123 : shift( 123, n );

был бы пессимизацией в большинстве случаев, и я не могу представить, что писатель компилятора реализует такую ​​вещь.

Изменить: AA сдвиг нулевых битов гарантированно будет иметь не влияет на перемещаемый объект.

3
ответ дан 30 November 2019 в 15:24
поделиться

О правильности arg << 0 или arg >> 0, без проблем, абсолютно нормально.

О возможных оптимизациях: Это не будет уменьшено до> nop <при вызове с константой what = 0 и / или bitcount = 0, если вы не объявите его как встроенный и не выберете оптимизацию (и выбранный вами компилятор понимает, что такое встроенный).

Итак , нижняя строка, оптимизируйте этот код, условно вызывая функцию только в том случае, если OR аргументов не равно нулю (как я полагаю, это самый быстрый способ проверить, что оба аргумента не равны нулю).

3
ответ дан 30 November 2019 в 15:24
поделиться

Чтобы сделать функцию несколько самодокументированной, вы можете изменить bitCount на unsigned, чтобы указать вызывающим абонентам, что отрицательное значение недопустимо.

1
ответ дан 30 November 2019 в 15:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: