powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Внутреннее устройство Extended
4 сообщений из 4, страница 1 из 1
Внутреннее устройство Extended
    #40001380
istrebitel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В проекте из за ошибки было неправильно считано число Extended типа. При попытке преобразовать его в строку выдавало мусор.
При попытке прибавить 0.1 превращалось в -NaN. Ошибку нашли, исправили, а мне стало интересно поразбираться. Сделал демо проект.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
function NumToBin(const Value; const Len: Integer): string;
var
  I, J: Integer;
  pb: PByte;
  BitNum: Integer;
begin
  SetLength(Result, Len * 8);
  BitNum := Length(Result);
  for I := 0 to Len - 1 do
  begin
    pb := PByte(@Value) + I;
    for J := 0 to 7 do
    begin
      if ((pb^ shr J) and 1) = 1
        then Result[BitNum] := '1'
        else Result[BitNum] := '0';
      Dec(BitNum);
    end;
  end;
end;

function FormatBin(const Value: string): string;
var
  ValLen: Integer;
begin
  ValLen := Length(Value);
  case ValLen of
    //Single
    4 * 8 : Result := Value[1] + ' ' + Copy(Value, 2, 8) + ' ' + Copy(Value, 10, ValLen - 10 + 1);
    //Real
    6 * 8 : Result := Value[1] + ' ' + Copy(Value, 2, 7) + ' ' + Copy(Value, 9, ValLen - 9 + 1);
    //Double
    8 * 8 : Result := Value[1] + ' ' + Copy(Value, 2, 11) + ' ' + Copy(Value, 13, ValLen - 13 + 1);
    //Extended
    10 * 8 : Result := Value[1] + ' ' + Copy(Value, 2, 15) + ' ' + Copy(Value, 17, ValLen - 10 + 1);
  else
    Result := Value;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ValidVal, InvalidVal: Extended;
  arr: array[0..9] of Byte absolute InvalidVal;
begin
  ValidVal := 0.372036854775808;
  InvalidVal := 0;
  //arr[7] := 64;
  //arr[7] := 128;
  arr[8] := 254;
  arr[9] := 63;
  Memo1.Clear;
  Memo1.Lines.Add(FormatBin(NumToBin(ValidVal, SizeOf(ValidVal))));
  Memo1.Lines.Add(FormatBin(NumToBin(InvalidVal, SizeOf(InvalidVal))));
  Memo1.Lines.Add(FloatToStr(ValidVal));
  //InvalidVal := InvalidVal + 0.1;
  Memo1.Lines.Add(FloatToStr(InvalidVal));
end;


Правда в нём при любой попытке взаимодействовать с числом (хоть прибавить 0,1 хоть FloatToStr) выдаёт
Код: plaintext
Invalid floating point operation

Переменная Знак Экспонента МантиссаValidVal 0 011111111111101 1011111001111011100111010101100001010110011011001000011111001111InvalidVal 0 011111111111110 0000000000000000000000000000000000000000000000000000000000000000
Почитал статейку ОСОБЕННОСТИ ВЕЩЕСТВЕННЫХ ЧИСЕЛ В DELPHI
Если все биты в экспоненте равны единице, а в матрице – нулю, то мы получаем комбинацию, известную как INF (от английского Infinity – бесконечность). Эта комбинация используется тогда, когда результат вычислений превышает максимально допустимое форматом число. В зависимости от значения бита s бесконечность может быть положительной или отрицательной. Если же при такой экспоненте в мантиссе хоть один бит не равен нулю, такая комбинация называется NAN (Not A Number – не число). Попытки использования комбинаций NAN или INF приводят к ошибке времени выполнения.

Несколько иначе устроен Extended. Кроме количественных отличий добавляется ещё и одно качественное: в мантиссе явно указывается первый разряд. То есть, мантисса 1010... интерпретируется как 1.01, а не как 1.101, как это было в типах Single и Float.

Суть вопроса в чём я правильно понимаю что старший бит мантиссы в Extended должен быть равен 1?
По факту InvalidVal это 0 * 2 в какой то степени.
...
Рейтинг: 0 / 0
Внутреннее устройство Extended
    #40001382
istrebitel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Демо.
...
Рейтинг: 0 / 0
Внутреннее устройство Extended
    #40001384
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
istrebitel,

авторBe careful using System.Extended if you are creating data files to share across platforms. Be aware that:

  • On Intel 32-bit Windows systems, the size of System.Extended is 10 bytes.
  • On Intel 32-bit macOS or iOS-Simulator systems, the size of System.Extended is 16 bytes in order to be compatible with BCCOSX.
  • On Intel Linux systems, the size of System.Extended is 16 bytes.
  • On Intel 64-bit Windows systems, however, the System.Extended type is an alias for System.Double, which is only 8 bytes. This difference can adversely affect numeric precision in floating-point operations.
  • On ARM system include iOS and Android, however, the System.Extended type is an alias for System.Double, which is only 8 bytes. This difference can adversely affect numeric precision in floating-point operations.

Если тебе по неким странным причинам не хватает double - посмотри на https://github.com/rvelthuis/DelphiBigNumbers
...
Рейтинг: 0 / 0
Внутреннее устройство Extended
    #40001385
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
22.09.2020 16:24, istrebitel пишет:
> Демо.

забавно
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
4 сообщений из 4, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Внутреннее устройство Extended
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]