Здравствуйте, AH20, Вы писали:
AH>С железки приходят числа с плавающей точкой в паскалевском формате real (6 байт). Нужно преобразовать его в стандартное 8 байтовое сишное число. Как? Ты уверен что 6 байт? Я просто такого формата не знаю. Знаю 4 байта, 8 байт и 10 байт. 6 байт не знаю.
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, AH20, Вы писали:
AH>>С железки приходят числа с плавающей точкой в паскалевском формате real (6 байт). Нужно преобразовать его в стандартное 8 байтовое сишное число. Как? WH> Ты уверен что 6 байт? Я просто такого формата не знаю. Знаю 4 байта, 8 байт и 10 байт. 6 байт не знаю.
Да, именно 6 байт — это эмулируемый формат. Мы ла лабах со студентами смотрели.
ИМХО можно написать небольшую прогу на паскале, которая принимает real, а выдает double (понятно, что в single может не поместиться).
Иначе — ручками разобрать формат — на мантиссу и порядок и сформировать заново в double.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, AH20, Вы писали:
AH>>С железки приходят числа с плавающей точкой в паскалевском формате real (6 байт). Нужно преобразовать его в стандартное 8 байтовое сишное число. Как? WH> Ты уверен что 6 байт? Я просто такого формата не знаю. Знаю 4 байта, 8 байт и 10 байт. 6 байт не знаю.
Нашёл такую функцию преобразования в 4 байтовое число... С уменьшением точности. Хотелось бы этого избежать.
float RealToFloat(char *r) //r - ptr to 6 byte long array (real Pascal);
{
// 6 byte pascal real goes like this:
// byte #0: bytes #1..5 (except MSB (left bit) in byte #5): MSB (left bit) in byte #5:
// (exp+129) (mantissa-1) as a binary fraction // sign (if==1 then minus)
// 8bit 39bit // 1bit
// 4 byte float:
// MSB (left bit) of byte #0: bits #1..8: bits #9..31
// sign (if==1 then minus) (exp+127) (mantissa-1) as a binary fraction
// 1 bit 8bit 23 bitunion{
long int s; // 4 bytes;float flt;
}un;
unsigned char e;
long int k;
if( r[0]==0 ) un.flt = 0;
else{
e=r[0]-2;// the float exp is biased by 127, not 129 as in real
memcpy(&un.s,&r[2],4); // mantissa (partial)
//ignore the first bit, set it to zero:
//after that, move the mantissa 8 bits to the right
un.s=(un.s & 0x7FFFFFFF) >> 8;
k=e;
// move exp 23 bits to the left
k <<= 23;
// get the sign from MSB of r[5] (left bit of right byte) and put it to the left of expif( (r[5] & 0x80) ) k |= 0x80000000;//(r[5] & 0x80)==1 only if MSB of r[5]==1
// k|=0x80000000 sets the first byte of k to 1
// k looks like this now:
// sign (1bit), then 23 bits (first 8 of this 23 contains exp+127, other contain zeroes)
// after that, merge k to the un.s
un.s |= k;
}
return un.flt;
}
Здравствуйте, AH20, Вы писали:
AH>Нашёл такую функцию преобразования в 4 байтовое число... С уменьшением точности. Хотелось бы этого избежать.
А почему именно на С писать надо?
Можно написать паскалевскую функцию, принимающую real, а выдающую результат double. А вызхвать из С паскалевскую прогу с одним параметром труда не составляет — модификатор pascal
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, AH20, Вы писали:
AH>>Нашёл такую функцию преобразования в 4 байтовое число... С уменьшением точности. Хотелось бы этого избежать. LVV>А почему именно на С писать надо? LVV>Можно написать паскалевскую функцию, принимающую real, а выдающую результат double. А вызхвать из С паскалевскую прогу с одним параметром труда не составляет — модификатор pascal
Не могу найти информацию о побитовом представлении паскалевских типов.
Их double точно совпадает с сишным double? Имеется в виду длина мантиссы и т.д.
Здравствуйте, AH20, Вы писали:
AH>>>Нашёл такую функцию преобразования в 4 байтовое число... С уменьшением точности. Хотелось бы этого избежать. LVV>>А почему именно на С писать надо? LVV>>Можно написать паскалевскую функцию, принимающую real, а выдающую результат double. А вызхвать из С паскалевскую прогу с одним параметром труда не составляет — модификатор pascal
AH>Не могу найти информацию о побитовом представлении паскалевских типов. AH>Их double точно совпадает с сишным double? Имеется в виду длина мантиссы и т.д.
Да
single = float, 4 байта
double = double, 8 байт
это работает НА ВСЕХ компиляторах, поскольку это стандарт IEEE реализованный в сопроцессоре Intel
extended = long double, 10 байт
Не везде выполняется, например Visual C++ long double = double.
а в Борландах — выполняется
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Да LVV>single = float, 4 байта LVV>double = double, 8 байт LVV>это работает НА ВСЕХ компиляторах, поскольку это стандарт IEEE реализованный в сопроцессоре Intel
LVV>extended = long double, 10 байт LVV>Не везде выполняется, например Visual C++ long double = double. LVV>а в Борландах — выполняется
Пишу на VC++. Нашёл описание типов... В общем то майкрософтовский стандарт не совпадает с IEEE:
Microsoft 8 byte real (see note below)
63 56 55 54 0
.----------------------------------------------.
| 8bits |s|msb 52 bit mantissa lsb|
`----------------------------------------------'
| | `------------ mantissa
| `----------------------------- sign bit
`--------------------------- biased exponent (401h, see below)
Здравствуйте, AH20, Вы писали:
LVV>>Да LVV>>single = float, 4 байта LVV>>double = double, 8 байт LVV>>это работает НА ВСЕХ компиляторах, поскольку это стандарт IEEE реализованный в сопроцессоре Intel
LVV>>extended = long double, 10 байт LVV>>Не везде выполняется, например Visual C++ long double = double. LVV>>а в Борландах — выполняется
AH>Пишу на VC++. Нашёл описание типов... В общем то майкрософтовский стандарт не совпадает с IEEE: AH>Вот как оказывается всё непросто.
Где такое описание?
double реализован аппаратно, поэтому микрософт не может ничего своего придумать.
В любой книжке по пентиуму про него написано.
Или это эмулируемый формат при отсутствии сопроцессора?
Или хдесь каким-то боком big-endian — little-endian?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, AH20, Вы писали:
AH>Здравствуйте, LaptevVV, Вы писали:
LVV>>Да LVV>>single = float, 4 байта LVV>>double = double, 8 байт LVV>>это работает НА ВСЕХ компиляторах, поскольку это стандарт IEEE реализованный в сопроцессоре Intel
LVV>>extended = long double, 10 байт LVV>>Не везде выполняется, например Visual C++ long double = double. LVV>>а в Борландах — выполняется
AH>Пишу на VC++. Нашёл описание типов... В общем то майкрософтовский стандарт не совпадает с IEEE:
Ты, видимо, что-то путаешь. Нет никакого майкрософтовского стандарта. VC6 пользуется родными плавающими форматами x86.
Кстати, оффтопичный вопрос про плавающие форматы. Я, помнится, где-то читал, что на x86 в 10-тибайтовом плавающем формате мантисса должна явно содержать все разряды, включая ведущую единицу. Т.е. соглашение о неявной ведущей единице, имеющее место в случае 4-хбайтового и 8-мибайтового плавающих форматов, не распространяется на 10-тибайтовый формат. Во-первых, правда ли это? Во-вторых, если правда, то как это согласуется со стандартом IEEE? Допускает ли он такую возможность?
Здравствуйте, Андрей Тарасевич, Вы писали:
АТ>Ты, видимо, что-то путаешь. Нет никакого майкрософтовского стандарта. VC6 пользуется родными плавающими форматами x86.
АТ>Кстати, оффтопичный вопрос про плавающие форматы. Я, помнится, где-то читал, что на x86 в 10-тибайтовом плавающем формате мантисса должна явно содержать все разряды, включая ведущую единицу. Т.е. соглашение о неявной ведущей единице, имеющее место в случае 4-хбайтового и 8-мибайтового плавающих форматов, не распространяется на 10-тибайтовый формат. Во-первых, правда ли это? Во-вторых, если правда, то как это согласуется со стандартом IEEE? Допускает ли он такую возможность?
1. Это действительно так. Сопроцессор интела имеет 8 10-байтных регистров, в которые можно загружать любые другие форматы сопроцессора. При этом неявная единица становится явной. Мантисса занимает 64 бита, порядок — 15 бит, первый бит — знак.
2. В стандарте IEE такого формата нет — есть только 32-битный и 64-битный. Его например, в Яве реализовали — там нет long double. Сопроцессор реализует оба этих формата в точности со стандартом, но операции выполняются на 80-битных регистрах.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Похоже. что это для фортрана, причем древнего, когда сопроцессора еще не было.
Возьми ЛЮБУЮ книгу по Пентюху — там форматы сопроцессора должны быть, Они именно такой вид в С++ и имеют.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>2. В стандарте IEE такого формата нет — есть только 32-битный и 64-битный. Его например, в Яве реализовали — там нет long double. Сопроцессор реализует оба этих формата в точности со стандартом, но операции выполняются на 80-битных регистрах.
Возможно я ошибаюсь и такой стандарт есть, но я из книжки Таненбаума по операционным системам о стандарте IEEE сведения взял. Там формат 10 байт отсутствует.
В другой книжке Таненбаума "Организация ЭВМ" — тоже только два формата: 32 и 64 бита.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, LaptevVV, Вы писали:
LVV>Там формат 10 байт отсутствует. LVV>В другой книжке Таненбаума "Организация ЭВМ" — тоже только два формата: 32 и 64 бита.
Стандарт IEEE-754 предусматривает т.н. расширенные (extended) форматы (п. 3.3), на реализацию которых дается достаточная степень свободы.
80-битный формат x87 полностью соответствует требованиям стандарта к "Double-Extended format".
Представление ведущей единицы в мантиссе оговаривается как implementation-defined.
Здравствуйте, AH20, Вы писали:
AH>Здравствуйте, LaptevVV, Вы писали:
AH>Пишу на VC++. Нашёл описание типов... В общем то майкрософтовский стандарт не совпадает с IEEE:
Здравствуйте, AH20, Вы писали:
AH>С железки приходят числа с плавающей точкой в паскалевском формате real (6 байт). Нужно преобразовать его в стандартное 8 байтовое сишное число. Как?
var
r:real48;
d:double;
begin
r:=123;
d:=r;
при этом вызывается функция из System
const
RealBias = 129;
ExtBias = $3FFF;
procedure _Real2Ext;//( val : Real ) : Extended;
asm
// -> EAX Pointer to value
// <- FST(0) Result
// the REAL data type has the following format:
// 8 bit exponent (bias 129), 39 bit fraction, 1 bit sign
MOV DH,[EAX+5] // isolate the sign bit
AND DH,80H
MOV DL,[EAX] // fetch exponent
TEST DL,DL // exponent zero means number is zero
JE @@zero
ADD DX,ExtBias-RealBias // adjust exponent bias
PUSH EDX // the exponent is at the highest address
MOV EDX,[EAX+2] // load high fraction part, set hidden bit
OR EDX,80000000H
PUSH EDX // push high fraction part