На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Разница в вычислениях при использовании х86 и 64х
    Здравствуйте.
    Проблема выглядит так:

    ExpandedWrap disabled
      procedure TForm1.FormCreate(Sender: TObject);
      var
        tmpReal: Real;
      begin
        tmpReal := (100/20000*1526)*100;
        ShowMessage(IntToStr(trunc((100/20000*1526)*100))+' - '+IntToStr(trunc(tmpReal)));
      end;


    Этот код даст разные сообщения при компиляции W32 и W64. Подскажите, пожалуйста, почему так?

    ЗЫЖ проверялось да Д10.2 и Д10.3. Если вы не верите или не хотите проверять, вот как это выглядит: https://www.youtube.com/watch?v=9fdip3DVReQ .
      Потому что у тебя не указан тип применяемый в первой матоперации в ShowMessage. По всей видимости разночтения пошли из-за того что дельфи, рассчитав значение еще на этапе компиляции, использовала разные типы.
      Ну как пример:
      - Extended for 32bit
      - Double for 64bit (в 64 битах строго говоря Extended из коробки не поддерживается).
        Есть где-то упоминание этого в документации Эмбы?

        Строго говоря, посчитав это на калькуляторе, получаем что минимальный используемый разряд мантиссы - 3, а разница в результате порождена во втором разряде. То есть погрешность от одной сотой до одной тысячной. Но ведь если погрешность расчётов так высока, то как тогда пишется огромное количество софта на Дельфях? Чем этот пример особенный? Чем эти цифры особенные?
          Rouse прав насчёт расчёта на этапе компиляции - в win32 загружается константа 762

          ExpandedWrap disabled
            00791750 B8FA020000       mov eax,$000002fa


          >если погрешность расчётов так высока
          Нет, если забыть о куче особенностей вещественных чисел. Далеко не все числа точно представимы во float

          И в Win32 c ними работает сопроцессор, а в Win64 в основном SSE-модуль (без Extended), поэтому могут быть некоторые отклонения.
          Сообщение отредактировано: MBo -
            Сама ситуация обнаружена когда эти цифры внутри переменных. Повторяемость ситуации с константами как бы намекает что проблема не в константе.
            А что за особенности вещественных чисел и при чём тут они? (если я правильно помню что такое вещественное число) В данном примере на каждом шаге вычислений всегда получается рациональное число. И если бы Float или Extended не мог точно хранить число 0.005 (а именно такое значение минимально при проведении расчётов), то поехало бы в страну вечной охоты 90% вычислений.

            Помогите, пожалуйста, понять чем этот пример особенный.
              >на каждом шаге вычислений всегда получается рациональное число.
              Вещественные точно представляют только некоторые рациональные числа

              >если бы Float или Extended не мог точно хранить число 0.005
              Дык не может...
              https://www.h-schmidt.net/FloatConverter/IEEE754.html
              Value actually stored in float: 0.004999999888241291046142578125

              В данном случае поможет Round вместо Trunc (если логика подходит)

              Вот почитать:
              http://www.delphikingdom.com/asp/viewitem.asp?catalogid=374
              https://docs.oracle.com/cd/E19957-01/806-35...g_goldberg.html
              Сообщение отредактировано: MBo -
                Поэкспериментировал с Round и Trunc и всё стало на свои места...
                Если подробно, возможный теоретический худший вариант, когда все компоненты при расчётах являются приближениями:
                99.(9)/19999.(9)*1525.(9)*99.(9) = 762.(9)
                Trunc и Round тут предсказуемо дадут разный результат. Но по хорошему, скорей всего, приближением представляется только тот результат расчётов, который без явной типизации.

                Спасибо за подсказку, пошёл правильно исправлять :).
                Сообщение отредактировано: Lem0nti -
                  А ту т есть вообще необходимость в таком порядке вычислять? Ведь при вычислении только в целых числах
                  ExpandedWrap disabled
                    100*1526*100 div 20000
                  даст точный результат
                    Вообще эта плавающая точка тот еще зверек.
                    Давеча вылезла ошибка у одного из клиентов, казалось бы обычное число 8.07875.
                    Но если это число было в Double и его присвоить переменной типа Currency то под 64 бита получим 8.0788, а под 32 - 8.0787 и дальше все рассчеты поплывут :wall:

                    Случайно наткнулись.

                    Выкрутится конечно можно примерно так:
                    ExpandedWrap disabled
                      function ConvertDoubleToCurrency(Value: Double): Currency;
                      begin
                        Value := Value * 10000;
                        Result := Round(Value) / 10000;
                      end;


                    Но есть еще неявные преобразования, поэтому похоже придется использовать кастомные типы и все преобразования делать через "class operator Implicit/Explicit"
                    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                    0 пользователей:


                    Рейтинг@Mail.ru
                    [ Script execution time: 0,0278 ]   [ 16 queries used ]   [ Generated: 23.04.24, 20:59 GMT ]