Странная работа функций Min и Max

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

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

Странная работа функций Min и Max

Сообщение John_Faa » 18.05.2022 12:53:22

Обнаружил, что в некоторых случаях функции Min и Max изменяют переданное в них
значение, например такой код

Код: Выделить всё
program MaxTest;
uses Math;
var
  XMin, XMax: Double;
const
  X = 51.354860533067;
begin
  XMax:= Max(X, 0);
  XMin:= Min(X, 100);
  WriteLn(X);
  WriteLn(XMax);
  WriteLn(XMin);
  ReadLn;
end.


выдаст такой результат:

5.1354860533066997E+001
5.1354862213134766E+001
5.1354862213134766E+001

Почему так происходит?
John_Faa
незнакомец
 
Сообщения: 1
Зарегистрирован: 18.05.2022 12:37:27

Re: Странная работа функций Min и Max

Сообщение runewalsh » 20.05.2022 11:06:53

Выглядит, будто для Min/Max выбираются перегрузки (Single, Single). Баг, сейчас зарепорчу.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Странная работа функций Min и Max

Сообщение Sharfik » 21.05.2022 01:41:35

Это не баг, а особенность вывода WriteLn. Число представляется в удобном для машины варианте - на окончание смотрите.
Код WriteLn(FloatToStr(XMax)); выдает то что автор хочет.
program MaxTest;
uses Math,SysUtils;
var
XMin, XMax: Double;
const
X = 51.354860533067;
begin
XMax:= Max(X, 0);
XMin:= Min(X, 100);
WriteLn(X);
WriteLn(FloatToStr(XMax));
WriteLn(XMin);
ReadLn;
end.


Это только в Delphi волшебным образом все делается само, а в FPC хорошим тоном является все делать самому. В том числе форматировать числа в текст, прежде чем вывести их как текст.

Просто вывод X будет таким же "странным"
program MaxTest;
uses Math,SysUtils;
const
X = 51.354860533067;
begin
WriteLn(X);
ReadLn;
end.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 759
Зарегистрирован: 20.07.2013 01:04:30

Re: Странная работа функций Min и Max

Сообщение runewalsh » 21.05.2022 03:27:28

Это баг, у X, неявного типизированного как double, который может сохранить 15 десятичных цифр без искажений, из-за приведения к single неправильным выбором перегрузки уцелело только 7 значащих цифр, здесь сделал пример кода, выводящий имена выбранных перегрузок.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Странная работа функций Min и Max

Сообщение Vadim » 21.05.2022 04:27:50

runewalsh писал(а):Это баг, у X, неявного типизированного как double

Кстати говоря, разный FPC "неявно" константы типизирует по разному. У меня, к примеру, FPC 64-х битный и Х из примера типизировался как Extended. Тоже баг?

Добавлено спустя 14 минут 56 секунд:
Sharfik писал(а):Просто вывод X будет таким же "странным"

Это от того, что представления программиста и WriteLn о том, как должно выглядеть "неточное" число - разные. ;-)
Я в таких случаях предпочитаю явно форматированный вывод, что-то типа такого:
Код: Выделить всё
program MaxTest;
uses Math,SysUtils;
const
  X = 51.354860533067;
begin
  WriteLn(X:15:12);
  ReadLn;
end.
Последний раз редактировалось Vadim 21.05.2022 05:27:54, всего редактировалось 1 раз.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Странная работа функций Min и Max

Сообщение Sharfik » 21.05.2022 05:19:34

runewalsh
Что вы уперлись в эти Min, Max? Они отрабатывают все что от них надо безупречно в кодах выше. Я привел пример, что просто вывод X без всего прочего в коде будет таким же.
Вопрос темы был:
Обнаружил, что в некоторых случаях функции Min и Max изменяют переданное в них значение

Ответ: Ничего они не изменяют, работает все как часы. Только пользователь пишет число в формате удобочитаемом человеку, а машина выдает в формате который у нее за основу прописан. Беглый поиск выдал что это стандарт IEEE 754. Любой инженерный калькулятор выдает эту ахинею непонятную человеку хоть раз в жизни его использования, потому что работает в разных режимах отображения вычислений. Программа, поскольку автор не потрудился конкретизировать как ему результат представлять выдает как положено с точки зрения матекатики. Никто ничего не портит. Если программист не будет заботится о конкретики того что выводит, то завтра программа будет неработоспособной и глючной.

**уже сделали тут одни, что UTF8 и ANSI на лету само конвертируется при работе с ОС, побить хочется умников. Был нормальный код, понятно что на выходе и на входе определенных функций надо было делать конвертирование, а теперь черти чего, не знаешь что ждать от вызываемых функций работающих с путями файлов.

Vadim, мне кажется цитаты не соответствуют моим словам. Ник не тот вставлен
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 759
Зарегистрирован: 20.07.2013 01:04:30

Re: Странная работа функций Min и Max

Сообщение Vadim » 21.05.2022 05:28:51

Sharfik
Прошу прощения, исправил. Видимо не на ту кнопку нажал "Быстрая цитата".
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Странная работа функций Min и Max

Сообщение runewalsh » 21.05.2022 12:01:25

Sharfik писал(а):Ответ: Ничего они не изменяют, работает все как часы.

Max(X, 0), если у Max есть версия с типом первого параметра, в точности равному типу X, должен выдать либо ровно X, либо ровно 0, никаких погрешностей здесь быть не может. Да и было бы неприятно, если бы Max(X, 0) или его разница с X могли выдать какое-нибудь −0,0000000001: этот Max может использоваться для подготовки аргумента для функции вроде Power(base, exponent), определённой для base≥0. Из-за неверного выбора перегрузки он приводит X к single, тем самым может выдать значение, не равное ни тому, ни другому.

Vadim писал(а):Кстати говоря, разный FPC "неявно" константы типизирует по разному. У меня, к примеру, FPC 64-х битный и Х из примера типизировался как Extended. Тоже баг?

Перегрузки Extended тоже подвержены этому багу:

Код: Выделить всё
{$ifndef cpui386} {$error compile for x86-32} {$endif}
uses
   Math;

const
   X = 51.354860533067;

begin
   writeln(sizeof(X)); // 10
   writeln(max(X, 0) = X); // FALSE
   writeln(max(X, single(0)) = X); // TRUE
end.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Странная работа функций Min и Max

Сообщение Дож » 21.05.2022 14:49:55

Sharfik писал(а):Ответ: Ничего они не изменяют, работает все как часы.

Хреновые часы получаются: 5.1354862213134766E+001 вместо 5.1354860533066997E+001
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Странная работа функций Min и Max

Сообщение Vadim » 21.05.2022 15:21:38

Дож писал(а):Хреновые часы получаются: 5.1354862213134766E+001 вместо 5.1354860533066997E+001

Если константу принудительно привести к нормальному типу DOUBLE, а не объявлять её по принципу "и так сойдёт...", то вывод будет тоже нормальный... ;-)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Странная работа функций Min и Max

Сообщение Sharfik » 22.05.2022 02:00:34

Дож писал(а):Хреновые часы получаются: 5.1354862213134766E+001 вместо 5.1354860533066997E+001

Эм, я думал автор про другое - отображение. Согласен, дурак.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 759
Зарегистрирован: 20.07.2013 01:04:30


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16

Рейтинг@Mail.ru