воскресенье, 9 июня 2019 г.

Спецификация Go: арифметические операторы

Арифметические операторы применяются к числовым значениям и дают результат того же типа, что и первый операнд. Четыре стандартных арифметических оператора (+, -, *, /) применяются к целым числам, числам с плавающей точкой и сложным типам; + также относится к строкам. Битовые логические операторы и операторы сдвига применяются только к целым числам.

+    sum                    integers, floats, complex values, strings
-    difference             integers, floats, complex values
*    product                integers, floats, complex values
/    quotient               integers, floats, complex values
%    remainder              integers

&    bitwise AND            integers
|    bitwise OR             integers
^    bitwise XOR            integers
&^   bit clear (AND NOT)    integers

<<   left shift             integer << unsigned integer
>>   right shift            integer >> unsigned integer

Целочисленные операторы

Для двух целочисленных значений x и y целочисленное отношение q = x / y и остаток r = x % y удовлетворяют следующим соотношениям:

x = q*y + r  и  |r| < |y|

х / у усекается до нуля ("усеченное деление", "truncated division").

 x     y     x / y     x % y
 5     3       1         2
-5     3      -1        -2
 5    -3      -1         2
-5    -3       1        -2

Единственное исключение из этого правила состоит в том, что если дивиденд x является самым отрицательным значением для типа int типа x, частное q = x / -1 равно x (и r = 0) из-за переполнения двух-комплементного целого числа из двух дополнений:

                         x, q
int8                     -128
int16                  -32768
int32             -2147483648
int64    -9223372036854775808

Если делитель является константой, он не должен быть нулевым. Если делитель равен нулю во время выполнения, возникает паника во время выполнения. Если дивиденд неотрицательный и делитель имеет постоянную степень 2, деление может быть заменено сдвигом вправо, а вычисление остатка может быть заменено побитовой операцией И (bitwise AND):

 x     x / 4     x % 4     x >> 2     x & 3
 11      2         3         2          3
-11     -2        -3        -3          1

Операторы сдвига смещают левый операнд на число смещения, указанное правым операндом. Они реализуют арифметические сдвиги, если левый операнд представляет собой целое число со знаком, и логические сдвиги, если это целое число без знака. Там нет верхнего предела на счет сдвига. Сдвиги ведут себя так, как будто левый операнд смещен n раз на 1 для числа сдвигов n. В результате x << 1 совпадает с x*2, а x >> 1 совпадает с x/2, но усекается до отрицательной бесконечности.

Для целочисленных операндов унарные операторы +, - и ^ определяются следующим образом:

+x                          это 0 + x
-x    negation              это 0 - x
^x    bitwise complement    это m ^ x  с m = "все биты устанавливаются в 1" для беззнакового (unsigned) x
                                      и  m = -1 для x со знаком (signed)

Переполнение целых чисел

Для целочисленных значений без знака (unsigned integer) операции +, -, * и << вычисляются по модулю 2n, где n - ширина в битах типа целого числа без знака. Грубо говоря, эти целочисленные операции без знака отбрасывают старшие биты при переполнении, и программы могут полагаться на "циклический переход".

Для целых чисел со знаком операции +, -, *, / и << могут легально переполняться, и результирующее значение существует и детерминировано определяется представлением целого числа со знаком, операцией и ее операндами. Переполнение не вызывает паники во время выполнения. Компилятор может не оптимизировать код при условии, что переполнения не происходит. Например, он может не предполагать, что x < x + 1 всегда верно.

Операторы для чисел с плавающей точкой

Для чисел с плавающей точкой и комплексных чисел +x - это то же самое, что и x, а -x - отрицание x. Результат деления с плавающей запятой или сложного деления на ноль не указан вне стандарта IEEE-754; возникновение паники во время выполнения зависит от реализации.

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

Например, в некоторых архитектурах предусмотрена инструкция «FMA», которая вычисляет x * y + z без округления промежуточного результата x * y. Следующие примеры показывают, когда реализация Go может использовать эту инструкцию:

// FMA включена при вычислении r, потому что x*y явно не округляется:
r  = x*y + z
r  = z;   r += x*y
t  = x*y; r = t + z
*p = x*y; r = *p + z
r  = x*y + float64(z)

// FMA выключена при вычислении r, потому что она будет пропускать округление x*y:
r  = float64(x*y) + z
r  = z; r += float64(x*y)
t  = float64(x*y); r = t + z

Конкатенация строк

Строки могут быть объединены с помощью оператора + или оператора присвоения +=

s := "hi" + string(c)
s += " and good bye"

Добавление строки создает новую строку путем объединения операндов.


Читайте также:


Комментариев нет:

Отправить комментарий