Руководство по Ada (Ada 2022)
G.2.3 Модель фиксированной арифметики
В строгом режиме предопределённые арифметические операции типа с фиксированной точкой должны удовлетворять требованиям точности, указанным здесь, и должны избегать переполнения или сигнализировать о нём в описанных ситуациях.
Требования к реализации
Требования к точности предопределённых операций арифметики с фиксированной точкой и преобразований, а также результаты отношений с операндами с фиксированной точкой приведены ниже.
Операнды операторов сложения, вычитания, абсолютного значения и сравнения с фиксированной точкой имеют один и тот же тип. Эти операции обязаны давать точный результат, если они не приводят к переполнению.
Умножения и деления допускаются между операндами любых двух типов с фиксированной точкой; результат должен быть (явным или неявным) преобразован в какой-либо другой числовой тип. Для целей определения правил точности умножение или деление и преобразование рассматриваются как единая операция, точность которой зависит от трёх типов (операндов и результата). Для типов с фиксированной точкой десятичной системы можно использовать атрибут T'Round для явного преобразования с округлением (см. 3.5.10).
Когда тип результата — тип с плавающей точкой, точность определяется в G.2.1. Для некоторых комбинаций типов операндов и результата в оставшихся случаях результат должен принадлежать малому набору значений, называемому идеальным множеством результатов; для других комбинаций достаточно принадлежать более широкому, определяемому реализацией множеству значений, называемому близким множеством результатов. Когда тип результата — тип с фиксированной точкой десятичной системы, идеальное множество результатов содержит единственное значение; таким образом, операции над десятичными типами всегда полностью определены.
Когда один из операндов умножения или деления с фиксированной точкой имеет тип universal_real, этот операнд не преобразуется неявным образом в обычном смысле, так как контекст не определяет уникальный целевой тип, но точность результата умножения или деления (то есть, должен ли результат принадлежать идеальному множеству результатов или лишь близкому множеству результатов) зависит от значения операнда типа universal_real и от типов другого операнда и результата.
Для умножения или деления с фиксированной точкой, математический результат которого (точный) v, и для преобразования значения v в тип с фиксированной точкой, идеальное множество результатов и близкое множество результатов определяются следующим образом:
- Если тип результата — обычный тип с фиксированной точкой со значением small s,
если v — целое кратное s, то идеальное множество результатов содержит только значение v;
иначе, оно содержит целое кратное s сразу ниже v и целое кратное s сразу выше v.
Близкое множество результатов — определяемое реализацией множество последовательных целых кратных s, содержащее идеальное множество результатов как подмножество.
- Если тип результата — десятичный тип со значением small s,
если v — целое кратное s, то идеальное множество результатов содержит только значение v;
иначе, если применяется усечение, то оно содержит только целое кратное s в направлении к нулю, в то время как если применяется округление, то оно содержит только ближайшее целое кратное s (при равенстве ближайших значений выбирается то, которое дальше от нуля).
Близкое множество результатов — определяемое реализацией множество последовательных целых кратных s, содержащее идеальное множество результатов как подмножество.
- Если тип результата — целочисленный тип,
если v — целое число, то идеальное множество результатов содержит только значение v;
иначе, оно содержит целое ближайшее к значению v (если v находится на одинаковом расстоянии от двух последовательных целых чисел, идеальное множество результатов содержит то, которое дальше от нуля).
Близкое множество результатов — определяемое реализацией множество последовательных целых чисел, содержащее идеальное множество результатов как подмножество.
Результат умножения или деления с фиксированной точкой должен принадлежать либо идеальному, либо близкому множеству результатов, как описано ниже, если не происходит переполнение. В следующих случаях, если тип результата — тип с фиксированной точкой, пусть s — его small; в противном случае, когда тип результата — целочисленный тип, пусть s = 1.0.
- Для умножения или деления, ни один из операндов которого не имеет тип universal_real, пусть l и r — значения smalls левого и правого операндов соответственно. Для умножения, если (l · r) / s — целое число или обратная величина целого числа (в этом случае smalls называются «совместимыми»), результат должен принадлежать идеальному множеству результатов; в противном случае — близкому множеству результатов. Для деления, если l / (r · s) — целое число или обратная величина целого числа (то есть, smalls совместимы), результат должен принадлежать идеальному множеству результатов; в противном случае — близкому множеству результатов.
- Для умножения или деления с одним операндом типа universal_real со значением v, обратите внимание, что всегда возможно разложить v как целое кратное «совместимого» small, но целое кратное может быть «слишком большим». Если существует разложение, в котором это кратное меньше некоторого определяемого реализацией предела, результат должен принадлежать идеальному множеству результатов; в противном случае — близкому множеству результатов.
Умножение P * Q операнда типа с фиксированной точкой F на операнд типа Integer, или наоборот, и деление P / Q операнда типа с фиксированной точкой F на операнд типа Integer также допускаются. В этих случаях результат имеет тип F; явное преобразование результата никогда не требуется. Требуемая точность в этих случаях такая же, как и для умножения F(P * Q) или деления F(P / Q), полученных путём интерпретации операнда целочисленного типа как типа с фиксированной точкой со значением small 1.0.
Точность результата преобразования из целочисленного или типа с фиксированной точкой в тип с фиксированной точкой, или из типа с фиксированной точкой в целочисленный тип, такая же, как и точность умножения значения источника на операнд с фиксированной точкой со значением small 1.0 и значением 1.0, как указано вышеприведёнными правилами. Результат преобразования из типа с плавающей точкой в тип с фиксированной точкой должен принадлежать близкому множеству результатов. Результат преобразования операнда universal_real в тип с фиксированной точкой должен принадлежать идеальному множеству результатов.
Возможнность переполнения результата предопределённой арифметической операции или преобразования, дающего результат типа с фиксированной точкой T, аналогична таковой для типов с плавающей точкой, за исключением того, что она связана с базовым диапазоном, а не с безопасным диапазоном. Если все разрешённые результаты принадлежат базовому диапазону T, то реализация должна предоставить один из разрешённых результатов; в противном случае
- если T'Machine_Overflows имеет значение True, реализация должна либо предоставить один из разрешённых результатов, либо вызвать Constraint_Error;
- если T'Machine_Overflows имеет значение False, результат определяется реализацией.