Функция Random в fpc-2.4.0.x86_64-linux

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
Физик
новенький
Сообщения: 28
Зарегистрирован: 26.06.2006 12:42:33

Функция 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
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

Откуда такие сведения?

Я вот вижу, что в ф-ции random: extended число типа cardinal (макс. значение $FFFFFFFF) делится на (1 shl 32), что на единицу больше, поэтому результат не может быть равен единице.
Физик
новенький
Сообщения: 28
Зарегистрирован: 26.06.2006 12:42:33

Сообщение Физик »

Как известно, функция ln не определена в нуле.

При достаточно большом количестве итераций в строке 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
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

Вот такой тест:

Код: Выделить всё

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.

Давай свой пример, на котором сыплется, попробуем разобраться...
Физик
новенький
Сообщения: 28
Зарегистрирован: 26.06.2006 12:42:33

Сообщение Физик »

Спасибо, за интерес!

Выяснил, что проблема в несогласованности типа переменных. Действительно, function ln(d: double) : double, a function Random : extended. Поэтому в ln(1-Random) под ln может оказаться ноль в «double измерении».

Как один из вариантов выхода я поставил проверку на ноль. Может это не оптимальный выход, но вроде заработало, по крайней мере час счёта – полёт нормальный.

Интересно, что для 32-bit ОС такой проблемы не наблюдается: задачи считаются месяцами, пока не снимешь вручную.
Max Rusov
постоялец
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Сообщение Max Rusov »

Не уверен насчет linux, но в Win64 Extended == Double
Физик
новенький
Сообщения: 28
Зарегистрирован: 26.06.2006 12:42:33

Сообщение Физик »

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
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

С Win64 понятно, там M$ решила что i387 больше не нужен.
В linux x86_64 этого явления нет.
Но даже если бы все extended и превращались в double, первоначальная проблема вроде не должна возникать...
Физик
новенький
Сообщения: 28
Зарегистрирован: 26.06.2006 12:42:33

Сообщение Физик »

Sergei I. Gorelkin писал(а):если бы все extended и превращались в double, первоначальная проблема вроде не должна возникать...


это не происходит и проблема возникает...
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

Дело не в точностях, ф-ция ln() для i387 разворачивается компилятором в ассемблерную команду той же точности, что и ее аргумент. Там что-то более мрачное. Сообщил в багтрекер: http://bugs.freepascal.org/view.php?id=15835
Max Rusov
постоялец
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Сообщение Max Rusov »

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
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

На 64-битных виндах M$ объявила команды FPU (i387) устаревшими. Предполагается, что вместо них будут использоваться инструкции SSE3 (или как оно там для x64 правильно называется?). Оно действительно удобнее, но не поддерживает extended точность. Ссылки на это можно найти в Сети.
Если винда перестанет сохранять регистры FPU при переключении задач, использовать их все равно никто (из пользователей винды) не сможет, Intel/AMD хоть образрабатывайся...
Ну а FPC просто действует в соответствии с официальной политикой.
Max Rusov
постоялец
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Сообщение Max Rusov »

Спасибо за пояснения. При портировании своей программы под Win64 столкнулся с проблемой - нужно было считывать из двоичного файла сохраненные предыдущей версией Extended числа. Задачу, вроде, решил при помощи ассемблерной вставки, с использованием сопроцессора. Но то, что Вы написали заставляет задуматься - всегда ли это будет работать...
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
Сообщения: 1409
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение Sergei I. Gorelkin »

Ну вот, оказывается все уже давным-давно исправлено, проблема существовала со времен 2.2.4, только исправление почему-то не попало в релиз 2.4.0. А я, как это в спешке обычно и бывает, тестировал не 2.5.1, а невесть что... После полной пересборки все заработало.
Ответить