kdv писал(а):не можешь врубиться - попробуй.
select 1/24, 1/23.99999 from rdb$database.
Попробовал. С 1/24 и так всё ясно -- округление до целого. А вот почему час в третьем диалекте FB равен 1/23.99999? и почему именно пять девяток, а не шесть? почему не 1/24.00000?. Попробовал следующее:
Код: Выделить всё
select 1/23.99999, 1/24.00000 from rdb$database
и был неприятно удивлён: результаты вычисления двух выражений идентичны при любом одинаковом количесте девяток и нулей от 1 до 9. При увеличении количества девяток более девяти точность 1/23.(9) падает, а вот точность 1/23.(0) с увеличением количества нулей только растёт вплоть до семнадцати нулей. С чем это связано?
Собственно вопрос Kotъ-Begemotъ'а был в другом, а именно в подсчёте кол-ва минут между двумя двумя timestamp'ами. И сколько я не экспериментировал, но чтобы получить точную разницу в часах, делить на (1/23.99999) или даже на (1/24.00000) нельзя, т.к. точность никудышняя. Гораздо проще и точнее умножать разницу между timestamp'ами на 24, что и советует Борланд.
kdv писал(а):Потом попробуй прибавить к этому current_timestamp.
и т.д.
Поэкспериментировал и с прибавкой к timestamp'у целого количества часов. Выяснил следующее.
Если к значению типа timestamp прибавлять h/23.(9) (где h - целое количество часов от 1 до 23), то точность вычислений растёт с увеличением количества девяток, и наилучший (но всё же
не точный) результат достигается при девяти девятках, а дальше точность падает в полном соответствии с предыдущими изысканиями о точности вычисления 1/23.(9).
Если к значению типа timestamp прибавлять h/24.(0), до полная точность (совпадение десятых миллисекунд) достигается при десяти и более нулях после точки.
Также полная точность достигается, если прибалять h/cast(24 as double precision).
Вывод, для прибавления к timestamp'у одного часа в третьем диалекте FB, чтобы не парить себе мозги, надо добавлять 1/cast(24 as double precition), а не 1/23.99999 или даже 1/24.00000.
Кому интересно, тестовый блок:
Код: Выделить всё
execute block returns (Hours integer, TimeF varchar(30),
Time1 varchar(30), Time2 varchar(30), Time3 varchar(30), Time4 varchar(30),
Time5 varchar(30), Time6 varchar(30), Time7 varchar(30), Time8 varchar(30),
Time9 varchar(30), Time10 varchar(30), Time11 varchar(30), Time12 varchar(30)
) as
declare variable Today timestamp;
begin
Hours = 0; Today = current_date;
while (Hours < 24) do begin
Hours = Hours + 1;
-- Для краткости убираем дату из результата
TimeF = cast(Today + Hours/cast(24 as double precision) as time);
Time1 = cast(Today + Hours/24.0 as time);
Time2 = cast(Today + Hours/24.00 as time);
Time3 = cast(Today + Hours/24.000 as time);
Time4 = cast(Today + Hours/24.0000 as time);
Time5 = cast(Today + Hours/24.00000 as time);
Time6 = cast(Today + Hours/24.000000 as time);
Time7 = cast(Today + Hours/24.0000000 as time);
Time8 = cast(Today + Hours/24.00000000 as time);
Time9 = cast(Today + Hours/24.000000000 as time);
Time10 = cast(Today + Hours/24.0000000000 as time);
Time11 = cast(Today + Hours/24.00000000000 as time);
Time12 = cast(Today + Hours/24.000000000000 as time);
suspend;
end
end
P.S. Для тестирования h/23.(9) заменить везде 24.0... на 23.9...