Числа
Набор числовых типов и операций с ними в Ficus схож с языками C/C++ и с большинством других языков программирования.
Одно существенное отличие от C/C++ и Python касается типа int. В C/C++ тип int чаще всего представляет собой 32-битное целое число, даже на 64-битных машинах. В Python начиная с версии 3.x тип int — это целое число произвольной точности. В Ficus тип int на 32-битных машинах является 32-битным числом, а на 64-битных — 64-битным. Важное замечание: в Ficus нет типа uint или unsigned.
Числовые типы не преобразуются друг в друга неявно. Например, если функция принимает аргумент типа int, а у вас имеется значение типа uint8, его нужно явно привести к типу int. Существуют три способа приведения числа из одного типа в другой:
- через оператор приведения типа
(expr :> целевой_тип):
val a = 34587345
val b = 987654321
val product = (a :> uint64) * b
(Оператор :> универсален и может также использоваться для преобразования чисел в строки, запроса интерфейсов класса и т.п.; подробности см. в разделе Объектно-ориентированное программирование.)
- через специальную функцию преобразования:
целевое_имя_типа()илиsat_целевое_имя_типа(), например,int8()преобразует число в типint8. Мы уже встречали функциюstring(), которая преобразует различные значения в строку. Функции видаsat_[u]intN()выполняют преобразование с насыщением, то есть обрезают аргумент вместо простого отбрасывания младших бит:
// псевдо-реализация sat_uint8()
fun sat_uint8(x: int) =
if x < 0 {0u8} else if x > 255 {255u8} else {uint8(x)}
- конверсия вещественного числа в целое — особый случай, для этого предусмотрены несколько функций:
round()— округление к ближайшему числуfloor()— округление к минус бесконечностиceil()— округление к плюс бесконечностиtrunc()— округление к нулю, аналогично C
Стандартный набор арифметических, поразрядных и сравнительных операторов в Ficus повторяет большинство других языков. Полный перечень доступных операций смотрите в разделе Выражения.
Аргументы бинарных операций могут иметь разные типы, в таких случаях применяются правила повышения типов, то есть оба аргумента приводятся к общему, достаточно широкому типу:
- до приведения, если
T1илиT2является типомint8,uint8,int16илиuint16, он приводится к типуint. - если оба типа совпадают (возможно, после предыдущего шага), результатом повышения будет именно этот общий тип.
- иначе, если один из типов — целое число, а другой — вещественное, результатом станет вещественный тип.
- если один из типов —
intилиint32, а другой —int64, результатом будетint64. - если один из типов —
uint32, а другой —int64илиuint64, результатом будетint64илиuint64. - если один из типов —
float, а другой —double, результатом будетdouble. - в противном случае проверщик типов выдаст ошибку, и нужно явно приводить аргументы к паре согласуемых типов.
Правила повышения применяются рекурсивно для массивов и кортежей при операциях .+, .-, .*, ./, при этом обработка осуществляется поэлементно.
Кроме того, есть полезные функции, работающие с числами:
min(a, b),max(a, b)— находят минимум/максимум двух чиселabs(x)— вычисляет абсолютное значение аргументаsign(x)— вычисляет знак аргумента (-1, 0 или 1)sqr(x)— возводит аргумент в квадрат, то есть x*xsqrt(x)— извлекает квадратный кореньsin(x),cos(x),exp(x),log(x),atan2(y, x)и прочие стандартные математические функции из модуля Math, подключаемого автоматически.