Побитовая операция "& 0x7FFFFFFF" нужна только для отрицательных чисел?
При добавлении новой пары в коллекцию Dictionary, как известно, первым делом сначала вычисляется хэш ключа. Затем над этим хэшем происходит побитовая операция & 0x7FFFFFFF, это можно увидеть в исходном коде коллекции.
У меня вопрос, если я все правильно понял, то эта операции нужна только на тот случай, если хэш окажется отрицательным числом, так как наш int может хранить отрицательные значения тоже. А результатом этой операции становиться другое число, которое всегда положительное.
Если все так и есть, то вместо:
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
int targetBucket = hashCode % buckets.Length;
Можно было использовать такой код:
int hashCode = comparer.GetHashCode(key);
if (hashCode < 0)
{
hashCode = hashCode * -1;
}
int targetBucket = hashCode % buckets.Length;
Верно?
Ответы (1 шт):
Краткий ответ - нет. И на то есть две причины. Во первых, Ваш вариант значительно хуже в плане производительности - он содержит сравнение и умножение. Сравнение это плохая операция для процессора - она может привести к большой просадке производительности. Читайте Предсказание переходов. Оптимизатор умный, может исправит, а может и нет.
Во вторых, Ваш вариант иногда не будет работать. Представьте себе число, которое состоит из 1 и нули. Это самое минимальное число, которое можно представить в данном формате. Если произвести с ним операцию И, оно просто превратится в ноль, который не является отрицательным числом. Но если его умножить на минус единицу... тут все становится интереснее.
Давайте рассмотрим на примере одного байта, так легче. Наше число это 10000000b == -128. Умножив на -1, получим 128. Но 128 это также 10000000...,которое вновь стает -128, так как не влазит в один байт. То есть, умножение минимального целого числа, представимого в данном "размере" на -1 дает его самого. А это явно не то, что нам нужно было.