Поведение типов с фиксированной точкой в операциях
Поведение типов с фиксированной точкой в операциях
Деление
При выполнении деления типов с фиксированной точкой диалекты 1 и 3 ведут себя по-разному.
В диалекте 3, когда оба операнда являются типами с фиксированной точкой, Firebird суммирует масштабы обоих операндов для определения масштаба результата (частного). Частное имеет точность 18. При проектировании запросов с выражениями, содержащими деление, убедитесь, что частное всегда будет иметь точность больше, чем любой из операндов, и примите меры предосторожности в случаях, когда точность потенциально может превысить допустимый максимум 18.
В диалекте 1 деление всегда создает частное типа DOUBLE PRECISION.
Примеры
В диалекте 3 частное от деления DECIMAL(12,3) на DECIMAL(9,2) будет DECIMAL(18,5). Масштабы суммируются:
SELECT 11223344.556/1234567.89 FROM RDB$DATABASE
Это дает 9.09090.
Посмотрим, чем отличается частное, когда этот же запрос выполняется в диалекте 1. Первый операнд трактуется как число DOUBLE PRECISION, потому что его точность (12) превышает максимум масштабируемого типа для диалекта 1. Частное также является числом DOUBLE PRECISION. Результат 9.09090917308727 по причине ошибок, присущих типам с плавающей точкой.
Для следующей таблицы, определенной в диалекте 3, операции деления дают различные результаты.
CREATE TABLE t1 (
i1 INTEGER,
i2 INTEGER,
n1 NUMERIC(16, 2),
n2 NUMERIC(16,2));
COMMIT;
INSERT INTO t1 VALUES (1, 3, 1.00, 3.00);
COMMIT;
Следующий запрос возвращает значение 0.33 типа NUMERIC(18,2), потому что сумма масштабов 0 (операнд 1) и 2 (операнд 2) равна 2:
SELECT i1/n2 from t1
Следующий запрос возвращает значение 0.3333 типа NUMERIC (18,4), потому что сумма масштабов двух операндов равна 4:
SELECT n1/n2 FROM t1
Деление целого на целое
Используя предыдущий пример, следующий запрос в диалекте 3 вернет целое 0, потому что каждый операнд имеет масштаб 0, следовательно, сумма масштабов будет 0:
SELECT i1/i2 FROM t1
В диалекте 1, как и в большинстве других СУБД, деление одного целого на другое целое даст результат с плавающей точкой типа DOUBLE PRECISION:
SELECT 1/3 AS RESULT FROM RDB$DATABASE
Это дает .333333333333333.
Хотя настоящее правило диалекта 1 является интуитивным для языков программирования, оно не соответствует стандарту SQL-92. Целые типы имеют масштаб 0. Для согласованности это требует, чтобы результат (частное) любой операции деления целого на целое соответствовал правилам масштабирования для чисел с фиксированной точкой и был бы целым.
Диалект 3 соответствует стандарту и усекает частное от операций деления целого на целое до целого. Следовательно, следующий оператор является неразумным:
SELECT 1/3 AS RESULT FROM RDB$DATABASE
Он вернет 0.
Если вам нужно сохранить дробную часть в результате (в частном) деления целого на целое в диалекте 3, убедитесь, что у одного из операндов присутствует нужный масштаб, или включите "множитель" в выражение, чтобы гарантировать масштаб результата.
Примеры:
SELECT 1.00/3 AS RESULT FROM RDB$DATABASE
Вернет .33.
SELECT (5 * 1.00)/2 AS RESULT FROM RDB$DATABASE
Этот вернет 2.50.
Диалект 1 базы данных с диалектом 3 клиента
База данных диалекта 1, которая была открыта клиентом диалекта 3, может преподнести некоторые сюрпризы в отношении деления целых чисел. Когда операция выполняет нечто, что приводит к проверке условия CHECK, или выполняется хранимая процедура или триггер, то осуществляемые действия основаны на диалекте, на котором CHECK, хранимая процедура или триггер были определены, а не на действующем диалекте, на котором приложение выполняет проверку, хранимую процедуру или триггер.
Например, в базе данных диалекта 1 таблица содержит столбцы MYCOL1 (INTEGER) и MYCOL2 (INTEGER) и следующее условие CHECK, которое было определено, когда база данных имела диалект 1:
CHECK(MYCOL1 / MYCOL2 >0.5)
Пусть теперь пользователь запускает isql или приложение, задав диалект 3. Программа пытается добавить строку в конвертированную базу данных:
INSERT INTO MYTABLE (COL1, COL2) VALUES (2,3);
Поскольку ограничение CHECK было определено в диалекте 1, оно вернет частное 0.666666666666667, и строка будет соответствовать условию CHECK.
Обратное также верно. Если то же ограничение CHECK было добавлено в базу данных диалекта 1 из клиента диалекта 3, то для ограничения будет сохранена арифметика диалекта 3. Предыдущий оператор INSERT не будет выполнен, потому что проверка вернет значение частного 0, которое нарушает это ограничение.
! ! !
СОВЕТ. Мораль всего этого: используйте базы данных диалекта 3 и всегда соединяйтесь с ними, применяя диалект 3. Если вы собираетесь использовать Firebird, то обновите все существующие базы данных до диалекта 3 - желательно описав новую базу данных и поместив в нее ваши старые данные - таким образом вы сохраните покой и сможете избежать уймы неприятных сюрпризов.
. ! .
Умножение и деление
Если оба операнда являются точными числами, умножение операндов даст точное число с масштабом, равным сумме масштабов операндов. Например,
CREATE TABLE t1 (
n1 NUMERIC(9,2),
n2 NUMERIC (9,3) ) ;
COMMIT;
INSERT INTO t1 VALUES (12.12, 123.123);
COMMIT;
Следующий запрос возвращает число 1492.25076, потому что n1 имеет масштаб 2, а n2 - масштаб 3. Сумма масштабов 5.
SELECT n1*n2 FROM t1
В диалекте 3 точность результата умножения чисел с фиксированной точкой будет равна 18. Нужно принять меры предосторожности, чтобы быть уверенным, что не будет переполнения результата при распространении масштаба в умножении.
В диалекте 1, если распространение масштаба приводит к тому, что вычисление даст результат с точностью больше 9, то результатом будет DOUBLE PRECISION.
Сложение и вычитание
Если все операнды являются точными числами, то сложение и вычитание операндов даст точное число с масштабом, равным максимальному масштабу операндов. Например,
CREATE TABLE t1 (
n1 NUMERIC(9, 2) ,
n2 NUMERIC(9, 3)) ;
COMMIT;
INSERT INTO t1 VALUES (12.12, 123.123);
COMMIT;
SELECT n1 + n2 FROM t1;
Этот запрос возвращает 135.243, выбирая максимальный масштаб операндов. Аналогично, следующий запрос возвращает число -111.003:
SELECT n1 - n2 FROM t1;
В диалекте 3 результат любого сложения или вычитания имеет тип NUMERIC(18,n). В диалекте 1 он имеет тип NUMERIC (9, n), где n - масштаб максимального операнда.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Типы данных фиксированной точности
Типы данных фиксированной точности Обозначения типов данных фиксированной точности получаются из обычных обозначений типов данных Win32, таких как DWORD или LONG, добавлением суффикса размера, как показано в табл. 16.1.Таблица 16.1. Типы данных фиксированной точности Тип
Пакет Общее поведение
Пакет Общее поведение Пакет Общее поведение является наиболее фундаментальным из всех подпакетов и определяет базовые понятия ядра, необходимые для всех элементов поведения. В этом пакете специфицирована семантика для динамических элементов, которые включены в другие
4.7. Поведение по-умолчанию
4.7. Поведение по-умолчанию В некоторых случаях механизм определения состояния не может распознать протокол обмена и, соответственно, не может выбрать стратегию обработки этого соединения. В этом случае он переходит к заданному по-умолчанию поведению. Поведение
Типы данных с фиксированной точкой
Типы данных с фиксированной точкой К этим типам данных относятся NUMERIC и DECIMAL. Часто звучит вопрос, чем NUMERIC отличается от DECIMAL. Оба этих типа имеют одинаковую разрядность - от 1 до 18 знаков, одинаковую точность - от нуля до разрядности.Напомним, что разрядность - это общее
3.1.3. Переполнение при арифметических операциях
3.1.3. Переполнение при арифметических операциях Переполнением принято называть ситуацию, когда при операциях над переменной результат выходит за пределы ее диапазона. Рассмотрим следующий пример (листинг 3.4, проект Overflow1 на компакт-диске).Листинг 3.4. Переполнение при
11.21. Реализация чисел с фиксированной точкой
11.21. Реализация чисел с фиксированной точкой ПроблемаТребуется обеспечить выполнение вычислений с вещественными числами, используя тип с фиксированной, а не с плавающей точкой.РешениеВ примере 11.40 представлена реализация вещественного числа с фиксированной точкой,
1.4. Поведение округления
1.4. Поведение округления Этот раздел обсуждает точность математического округления для функции ROUND() и для вставок в столбцы с типами с точным значением.Функция ROUND() работает по-разному в зависимости от того, является ли параметр точным или приблизительным числом:Для
Масштабируемые типы с фиксированной точкой
Масштабируемые типы с фиксированной точкой Типы с фиксированной точкой позволяют управлять числами, которые должны вычисляться с дробной частью, задающейся количеством цифр после десятичной точки, или масштабом. Обычно масштабируемые типы нужны для финансовых
Символьные данные фиксированной длины
Символьные данные фиксированной длины Строковые типы данных фиксированной длины в Firebird используются для хранения строк, длина которых является одной и той же или очень близкой, либо там, где фор- мат или относительная позиция символов может передавать семантическое
1.14 Еще об операциях
1.14 Еще об операциях Другое направление развития – снабдить вектора операциями:class Vec : public vector (* public: Vec(int s) : (s) (**) Vec(Vec amp;); ~Vec() (**) void operator=(Vec amp;); void operator*=(Vec amp;); void operator*=(int); //... *);Обратите внимание на способ определения конструктора производного класса, Vec::Vec(), когда он
Субкультурное поведение
Субкультурное поведение Существует понятие культурно-речевого статуса, то есть принадлежности индивида к конкретному типу языковой культуры. Выделяют следующие формы языков: литературный, разговорный, просторечие, территориальные диалекты, социальные диалекты (язык
Как мы планируем релизы и составляем контракты с фиксированной стоимостью
Как мы планируем релизы и составляем контракты с фиксированной стоимостью Иногда нужно планировать дальше, чем на один спринт вперед. Это типичная ситуация для контрактов с фиксированной стоимостью, когда нам приходится планировать наперед, или же есть риск подписаться