Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Внутреннее устройство Extended / 4 сообщений из 4, страница 1 из 1
22.09.2020, 16:23
    #40001380
istrebitel
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Внутреннее устройство Extended
В проекте из за ошибки было неправильно считано число 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
22.09.2020, 16:24
    #40001382
istrebitel
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Внутреннее устройство Extended
Демо.
...
Рейтинг: 0 / 0
22.09.2020, 16:27
    #40001384
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Внутреннее устройство Extended
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
22.09.2020, 16:32
    #40001385
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Внутреннее устройство Extended
22.09.2020 16:24, istrebitel пишет:
> Демо.

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


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