При позиционном сложении, вычитании и умножении чисел без знака для получения результатов без знака более значимые цифры ввода не влияют на менее значимые цифры результата. Это применимо как к двоичной арифметике, так и к десятичной арифметике. Это также применимо к знаковой арифметике с дополнением до двух, но не к знаковой арифметике со знаком.
Однако мы должны быть осторожны, беря правила из двоичной арифметики и применяя их к C (я полагаю, что C ++ имеет те же правила, что и C в этом материале, но я не уверен на 100%), потому что арифметика C имеет некоторые загадочные правила, которые могут нас сбить вверх. Беззнаковая арифметика в C подчиняется простым правилам двоичного переноса, но подписанное арифметическое переполнение является неопределенным поведением. Хуже того, при некоторых обстоятельствах C автоматически «продвигает» беззнаковый тип до (подписанного) int.
Неопределенное поведение в C может быть особенно коварным. Тупой компилятор (или компилятор с низким уровнем оптимизации), скорее всего, сделает то, что вы ожидаете, исходя из вашего понимания двоичной арифметики, в то время как оптимизирующий компилятор может странным образом сломать ваш код.
Итак, возвращаясь к формуле в вопросе, эквивалентность зависит от типов операндов.
Если они представляют собой целые числа без знака, размер которых больше или равен размеру, int
то поведение оператора сложения при переполнении четко определяется как простой двоичный цикл. Независимо от того, маскируем ли мы старшие 24 бита одного операнда перед операцией сложения, это не влияет на младшие биты результата.
Если это целые числа без знака, размер которых меньше, int
то они будут повышены до (подписанные) int
. Переполнение целых чисел со знаком является неопределенным поведением, но, по крайней мере, на каждой платформе, с которой я столкнулся, разница в размере между разными целыми типами достаточно велика, чтобы одно добавление двух продвинутых значений не привело к переполнению. Итак, мы снова можем вернуться к просто двоичному арифметическому аргументу, чтобы считать утверждения эквивалентными.
Если они представляют собой целые числа со знаком, размер которых меньше int, то опять же переполнение не может произойти, и в реализациях дополнения до двух мы можем полагаться на стандартный двоичный арифметический аргумент, чтобы сказать, что они эквивалентны. В реализациях знаковой величины или дополнений они не были бы эквивалентными.
OTOH, если a
и b
были целыми числами со знаком , размер которых был больше или равен размеру int, то даже в реализациях дополнения до двух есть случаи, когда один оператор был бы четко определен, а другой - неопределенным поведением.
Math.random()
возвращать целое число или двойные на [0,1)? Я не думаю, что ваш сценарий (лучшее, что я могу сказать) вообще отражает поставленную вами проблему.