Функция Random в fpc-2.4.0.x86_64-linux
Модератор: Модераторы
Функция Random в fpc-2.4.0.x86_64-linux
Никто не замечал, что в fpc-2.4.0.x86_64-linux функция Random генерирует случайное число из (0;1], тогда как обычно принято из [0;1).
- Sergei I. Gorelkin
- энтузиаст
- Сообщения: 1409
- Зарегистрирован: 24.07.2005 14:40:41
- Откуда: Зеленоград
Откуда такие сведения?
Я вот вижу, что в ф-ции random: extended число типа cardinal (макс. значение $FFFFFFFF) делится на (1 shl 32), что на единицу больше, поэтому результат не может быть равен единице.
Я вот вижу, что в ф-ции random: extended число типа cardinal (макс. значение $FFFFFFFF) делится на (1 shl 32), что на единицу больше, поэтому результат не может быть равен единице.
Как известно, функция ln не определена в нуле.
При достаточно большом количестве итераций в строке ln(1-Random) или ln(Random) появляется «Runtime error 200». Из чего можно сделать вывод, что Random включает как 0 так и 1.
Однако, дело может быть и в типе переменных. Например, Random – Extended, а ln пределена для Single. Честно говоря, я не знаю
.
При достаточно большом количестве итераций в строке ln(1-Random) или ln(Random) появляется «Runtime error 200». Из чего можно сделать вывод, что Random включает как 0 так и 1.
Однако, дело может быть и в типе переменных. Например, Random – Extended, а ln пределена для Single. Честно говоря, я не знаю
- Sergei I. Gorelkin
- энтузиаст
- Сообщения: 1409
- Зарегистрирован: 24.07.2005 14:40:41
- Откуда: Зеленоград
Вот такой тест:
выдает:
2.3283064365386963E-0010
-2.2180709777918250E+0001
т.е. вроде как все в ожидаемых пределах. Единственное отличие - компилятор 2.5.1 из svn.
Давай свой пример, на котором сыплется, попробуем разобраться...
Код: Выделить всё
var
sm: cardinal;
l: extended;
begin
// максимальное 32-битное беззнаковое
sm := $FFFFFFFF;
// делаем то же, что и ф-ция random: extended
l := sm * (extended(1.0)/(int64(1) shl 32));
writeln(1-l);
writeln(ln(1-l));
end.
выдает:
2.3283064365386963E-0010
-2.2180709777918250E+0001
т.е. вроде как все в ожидаемых пределах. Единственное отличие - компилятор 2.5.1 из svn.
Давай свой пример, на котором сыплется, попробуем разобраться...
Спасибо, за интерес!
Выяснил, что проблема в несогласованности типа переменных. Действительно, function ln(d: double) : double, a function Random : extended. Поэтому в ln(1-Random) под ln может оказаться ноль в «double измерении».
Как один из вариантов выхода я поставил проверку на ноль. Может это не оптимальный выход, но вроде заработало, по крайней мере час счёта – полёт нормальный.
Интересно, что для 32-bit ОС такой проблемы не наблюдается: задачи считаются месяцами, пока не снимешь вручную.
Выяснил, что проблема в несогласованности типа переменных. Действительно, function ln(d: double) : double, a function Random : extended. Поэтому в ln(1-Random) под ln может оказаться ноль в «double измерении».
Как один из вариантов выхода я поставил проверку на ноль. Может это не оптимальный выход, но вроде заработало, по крайней мере час счёта – полёт нормальный.
Интересно, что для 32-bit ОС такой проблемы не наблюдается: задачи считаются месяцами, пока не снимешь вручную.
Не уверен насчет linux, но в Win64 Extended == Double
Table 3.4: Supported Real types
Type Range Significant digits Size
Real platform dependant ??? 4 or 8
Single 1.5E-45 .. 3.4E38 7-8 4
Double 5.0E-324 .. 1.7E308 15-16 8
Extended 1.9E-4932 .. 1.1E4932 19-20 10
Type Range Significant digits Size
Real platform dependant ??? 4 or 8
Single 1.5E-45 .. 3.4E38 7-8 4
Double 5.0E-324 .. 1.7E308 15-16 8
Extended 1.9E-4932 .. 1.1E4932 19-20 10
- Sergei I. Gorelkin
- энтузиаст
- Сообщения: 1409
- Зарегистрирован: 24.07.2005 14:40:41
- Откуда: Зеленоград
С Win64 понятно, там M$ решила что i387 больше не нужен.
В linux x86_64 этого явления нет.
Но даже если бы все extended и превращались в double, первоначальная проблема вроде не должна возникать...
В linux x86_64 этого явления нет.
Но даже если бы все extended и превращались в double, первоначальная проблема вроде не должна возникать...
Sergei I. Gorelkin писал(а):если бы все extended и превращались в double, первоначальная проблема вроде не должна возникать...
это не происходит и проблема возникает...
- Sergei I. Gorelkin
- энтузиаст
- Сообщения: 1409
- Зарегистрирован: 24.07.2005 14:40:41
- Откуда: Зеленоград
Дело не в точностях, ф-ция ln() для i387 разворачивается компилятором в ассемблерную команду той же точности, что и ее аргумент. Там что-то более мрачное. Сообщил в багтрекер: http://bugs.freepascal.org/view.php?id=15835
Sergei I. Gorelkin писал(а):С Win64 понятно, там M$ решила что i387 больше не нужен.
В linux x86_64 этого явления нет.
Это не понял. Система команд для этих процессоров разрабатывалась Intel и AMD - при чем здесь M$? Почему FPC не поддерживает Extended под Win64 я до сих пор не понимаю. Может Вы объясните?
- Sergei I. Gorelkin
- энтузиаст
- Сообщения: 1409
- Зарегистрирован: 24.07.2005 14:40:41
- Откуда: Зеленоград
На 64-битных виндах M$ объявила команды FPU (i387) устаревшими. Предполагается, что вместо них будут использоваться инструкции SSE3 (или как оно там для x64 правильно называется?). Оно действительно удобнее, но не поддерживает extended точность. Ссылки на это можно найти в Сети.
Если винда перестанет сохранять регистры FPU при переключении задач, использовать их все равно никто (из пользователей винды) не сможет, Intel/AMD хоть образрабатывайся...
Ну а FPC просто действует в соответствии с официальной политикой.
Если винда перестанет сохранять регистры FPU при переключении задач, использовать их все равно никто (из пользователей винды) не сможет, Intel/AMD хоть образрабатывайся...
Ну а FPC просто действует в соответствии с официальной политикой.
Спасибо за пояснения. При портировании своей программы под Win64 столкнулся с проблемой - нужно было считывать из двоичного файла сохраненные предыдущей версией Extended числа. Задачу, вроде, решил при помощи ассемблерной вставки, с использованием сопроцессора. Но то, что Вы написали заставляет задуматься - всегда ли это будет работать...
- Sergei I. Gorelkin
- энтузиаст
- Сообщения: 1409
- Зарегистрирован: 24.07.2005 14:40:41
- Откуда: Зеленоград
Ну вот, оказывается все уже давным-давно исправлено, проблема существовала со времен 2.2.4, только исправление почему-то не попало в релиз 2.4.0. А я, как это в спешке обычно и бывает, тестировал не 2.5.1, а невесть что... После полной пересборки все заработало.
