cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
lala
Level VII

怎样将二进制文件中的指定字节转化为浮点数字?

例如将图中的第一行04——07字节转化为浮点数字,感谢专家!

2021-09-01_145427.png

正确的结果是 : 1006.27

二进制文件如下:

598A0F0548917B44F6C87B44855B7B44D7637B44DA57BE45140B000000000000
3 ACCEPTED SOLUTIONS

Accepted Solutions
Craige_Hales
Super User

Re: 怎样将二进制文件中的指定字节转化为浮点数字?

 

 

filename = Save Text File(
	"$temp/deleteme.bin",
	Hex To Blob( "598A0F0548917B44F6C87B44855B7B44D7637B44DA57BE45140B000000000000" )
);

// load the entire file. You could use the blob() parameter
// to load a smaller part of the file by offset and length.
blobdata = Load Text File( filename, blob() );

// convert the binary data to a matrix. The 4 means 4 byte chunks
// and "little" means the least significant byte comes first (little endian.)
numbers = Blob To Matrix( blobdata, "float", 4, "little" ); 

// print the values; JMP uses 8-byte floating point and will 
// display more resolution than is actually available.
For( i = 1, i <= N Rows( numbers ), i += 1,
	Write( "\!n", i, " ", numbers[i] )
);

1 6.74923813801151e-36
2 1006.27001953125
3 1007.14001464844
4 1005.42999267578
5 1005.55999755859
6 6090.9814453125
7 3.97408244482518e-42
8 0

 

 

There is a similar function, Matrix To Blob, for converting the other direction.

 

4-byte floats have 6 or 7 significant digits. 8-byte floats have 15 or 16 significant digits.

https://en.wikipedia.org/wiki/Single-precision_floating-point_format

https://en.wikipedia.org/wiki/Double-precision_floating-point_format

If you try to use the windows hex calculator, which has a convenient  bits display, be sure to reverse the bytes.

48917B44 -> 447B9148 -> 0 10001000 11110111001000101001000 -> 2^(136-127) * (1+1/2+1/4+1/8+1/16+0/32+1/64 +...)

 

Craige

View solution in original post

Craige_Hales
Super User

Re: 怎样将二进制文件中的指定字节转化为浮点数字?

You could make a graph of the data like this. It looks like there are some outliers!

data extracted from the zip file and graphed to see outliers.data extracted from the zip file and graphed to see outliers.

/*
00 to 01 bytes: indicates the date. If the value is num, the date calculation method is as follows:
year=floor(num/2048)+2004;
month=floor(mod(num,2048)/100);
day=mod(mod(num,2048),100);

02 to 03 bytes: indicates the number of minutes from 0 o 'clock to the present

04 to 07 bytes:  float
08 to 11 bytes:  float
12 to 15 bytes:  float
16 to 19 bytes:  float
20 to 23 bytes:  float

24 to 27 bytes:  integer
28 to 31 bytes :(reserved)
*/
za = Open( "z:/445.zip", "zip" ); // open the zip file
datasetname = (za << dir)[1];
blobdata = za << read( datasetname, Format( blob ) ); // load the member as a blob
//
// the following 3 lines import ALL of the data each time. Later, 
// only use the columns that were really in that format.
//
integer2 = Blob To Matrix( blobdata, "uint", 2, "little", 16 ); // get the 2-byte unsigned ints for columns 0-1 and 2-3
integer4 = Blob To Matrix( blobdata, "uint", 4, "little", 8 ); // get the 4-byte unsigned ints for columns 24-27 and 28-31
float4 = Blob To Matrix( blobdata, "float", 4, "little", 8 ); // get the 4-byte floats for columns 4-23

// pre-process the matrix columns; no explicit loop is required...
years = Floor( integer2[0, 1] / 2048 ) + 2004;
months = Floor( Mod( integer2[0, 1], 2048 ) / 100 );
days = Mod( Mod( integer2[0, 1], 2048 ), 100 );
seconds = 60 * integer2[0, 2];

// create a table. You could also use new table, but the v1...v5 would be a little more code to type
dt = As Table(
	years,
	months,
	days,
	seconds,
	float4[0, 2 :: 6],
	integer4[0, 7 :: 8],
	<<columnnames( {"year", "month", "day", "second", "v1", "v2", "v3", "v4", "v5", "xx", "reserved"} )
);

// add a JMP date-time formula column
dt << New Column( "date",
	Numeric,
	"Continuous",
	Format( "yyyy-mm-ddThh:mm:ss", 19, 0 ),
	Input Format( "yyyy-mm-ddThh:mm:ss", 0 ),
	Formula( Date DMY( :day, :month, :year ) + :second ),
	set selected
);
dt << run formulas; // make sure the formula completes

// clean up a bit
dt << move selected columns( to first );
dt << Clear Column Selection();
dt:date << deleteformula;
dt << deletecolumns( {"year", "month", "day", "second"} );
dt << setname(datasetname);
dt << Optimize Display;

// make a graph
dt << Graph Builder(
	Size( 1125, 610 ),
	Show Control Panel( 0 ),
	Variables( X( :date ), Y( :v5 ), Y( :v4 ), Y( :v3 ), Y( :v2 ), Y( :v1 ), Y( :xx ) ),
	Elements( Position( 1, 1 ), Points( X, Y, Legend( 57 ) ) ),
	Elements( Position( 1, 2 ), Points( X, Y, Legend( 59 ) ) ),
	Elements( Position( 1, 3 ), Points( X, Y, Legend( 61 ) ) ),
	Elements( Position( 1, 4 ), Points( X, Y, Legend( 63 ) ) ),
	Elements( Position( 1, 5 ), Points( X, Y, Legend( 65 ) ) ),
	Elements( Position( 1, 6 ), Points( X, Y, Legend( 67 ) ) ),
	SendToReport( Dispatch( {}, "graph title", TextEditBox, {Set Text( datasetname )} ) )
);
Craige

View solution in original post

Craige_Hales
Super User

Re: 怎样将二进制文件中的指定字节转化为浮点数字?

was there a message in the log?

 

all of those arrays (years,months,days,seconds) will need the same treatment: years[r-479::r], for example.

 

It might be easier to delete unwanted rows from the table after creating it. Try using the date column to select the range you care about.

 

Craige

View solution in original post

12 REPLIES 12
lala
Level VII

回复: 怎样将二进制文件中的指定字节转化为浮点数字?

excel VBA

2021-09-01_151051.png

lala
Level VII

回复: 怎样将二进制文件中的指定字节转化为浮点数字?

这个函数实现不了

CopyMemory v, b(0), 4    
Craige_Hales
Super User

Re: 怎样将二进制文件中的指定字节转化为浮点数字?

 

 

filename = Save Text File(
	"$temp/deleteme.bin",
	Hex To Blob( "598A0F0548917B44F6C87B44855B7B44D7637B44DA57BE45140B000000000000" )
);

// load the entire file. You could use the blob() parameter
// to load a smaller part of the file by offset and length.
blobdata = Load Text File( filename, blob() );

// convert the binary data to a matrix. The 4 means 4 byte chunks
// and "little" means the least significant byte comes first (little endian.)
numbers = Blob To Matrix( blobdata, "float", 4, "little" ); 

// print the values; JMP uses 8-byte floating point and will 
// display more resolution than is actually available.
For( i = 1, i <= N Rows( numbers ), i += 1,
	Write( "\!n", i, " ", numbers[i] )
);

1 6.74923813801151e-36
2 1006.27001953125
3 1007.14001464844
4 1005.42999267578
5 1005.55999755859
6 6090.9814453125
7 3.97408244482518e-42
8 0

 

 

There is a similar function, Matrix To Blob, for converting the other direction.

 

4-byte floats have 6 or 7 significant digits. 8-byte floats have 15 or 16 significant digits.

https://en.wikipedia.org/wiki/Single-precision_floating-point_format

https://en.wikipedia.org/wiki/Double-precision_floating-point_format

If you try to use the windows hex calculator, which has a convenient  bits display, be sure to reverse the bytes.

48917B44 -> 447B9148 -> 0 10001000 11110111001000101001000 -> 2^(136-127) * (1+1/2+1/4+1/8+1/16+0/32+1/64 +...)

 

Craige
lala
Level VII

Re: 怎样将二进制文件中的指定字节转化为浮点数字?

感谢专家!

这个二进制文件中的

00、01字节——年月日

02、03字节——时分

2021-09-01_145427.png

 

这样代码中的是否要增加分段?再次感谢!

numbers = Blob To Matrix( blobdata, "float", 4, "little" ); 

 

Craige_Hales
Super User

Re: 怎样将二进制文件中的指定字节转化为浮点数字?

You can process those four bytes as either four 1- byte uint or two 2- byte uint. Uint means unsigned integer. Instead of float, use uint. You will have to figure out how they represent the time, it isn't obvious with only one example that is not decoded.

Craige
lala
Level VII

Re: 怎样将二进制文件中的指定字节转化为浮点数字?

我还有没有能力进行这种操作。

我将整个文件上传、它有5070行这样结构的数据。

看看要如何编码?

谢谢!

 

00 to 01 bytes: indicates the date. If the value is num, the date calculation method is as follows:
year=floor(num/2048)+2004;
month=floor(mod(num,2048)/100);
day=mod(mod(num,2048),100);

02 to 03 bytes: indicates the number of minutes from 0 o 'clock to the present

04 to 07 bytes:  float
08 to 11 bytes:  float
12 to 15 bytes:  float
16 to 19 bytes:  float
20 to 23 bytes:  float

24 to 27 bytes:  integer
28 to 31 bytes :(reserved)
Craige_Hales
Super User

Re: 怎样将二进制文件中的指定字节转化为浮点数字?

You could make a graph of the data like this. It looks like there are some outliers!

data extracted from the zip file and graphed to see outliers.data extracted from the zip file and graphed to see outliers.

/*
00 to 01 bytes: indicates the date. If the value is num, the date calculation method is as follows:
year=floor(num/2048)+2004;
month=floor(mod(num,2048)/100);
day=mod(mod(num,2048),100);

02 to 03 bytes: indicates the number of minutes from 0 o 'clock to the present

04 to 07 bytes:  float
08 to 11 bytes:  float
12 to 15 bytes:  float
16 to 19 bytes:  float
20 to 23 bytes:  float

24 to 27 bytes:  integer
28 to 31 bytes :(reserved)
*/
za = Open( "z:/445.zip", "zip" ); // open the zip file
datasetname = (za << dir)[1];
blobdata = za << read( datasetname, Format( blob ) ); // load the member as a blob
//
// the following 3 lines import ALL of the data each time. Later, 
// only use the columns that were really in that format.
//
integer2 = Blob To Matrix( blobdata, "uint", 2, "little", 16 ); // get the 2-byte unsigned ints for columns 0-1 and 2-3
integer4 = Blob To Matrix( blobdata, "uint", 4, "little", 8 ); // get the 4-byte unsigned ints for columns 24-27 and 28-31
float4 = Blob To Matrix( blobdata, "float", 4, "little", 8 ); // get the 4-byte floats for columns 4-23

// pre-process the matrix columns; no explicit loop is required...
years = Floor( integer2[0, 1] / 2048 ) + 2004;
months = Floor( Mod( integer2[0, 1], 2048 ) / 100 );
days = Mod( Mod( integer2[0, 1], 2048 ), 100 );
seconds = 60 * integer2[0, 2];

// create a table. You could also use new table, but the v1...v5 would be a little more code to type
dt = As Table(
	years,
	months,
	days,
	seconds,
	float4[0, 2 :: 6],
	integer4[0, 7 :: 8],
	<<columnnames( {"year", "month", "day", "second", "v1", "v2", "v3", "v4", "v5", "xx", "reserved"} )
);

// add a JMP date-time formula column
dt << New Column( "date",
	Numeric,
	"Continuous",
	Format( "yyyy-mm-ddThh:mm:ss", 19, 0 ),
	Input Format( "yyyy-mm-ddThh:mm:ss", 0 ),
	Formula( Date DMY( :day, :month, :year ) + :second ),
	set selected
);
dt << run formulas; // make sure the formula completes

// clean up a bit
dt << move selected columns( to first );
dt << Clear Column Selection();
dt:date << deleteformula;
dt << deletecolumns( {"year", "month", "day", "second"} );
dt << setname(datasetname);
dt << Optimize Display;

// make a graph
dt << Graph Builder(
	Size( 1125, 610 ),
	Show Control Panel( 0 ),
	Variables( X( :date ), Y( :v5 ), Y( :v4 ), Y( :v3 ), Y( :v2 ), Y( :v1 ), Y( :xx ) ),
	Elements( Position( 1, 1 ), Points( X, Y, Legend( 57 ) ) ),
	Elements( Position( 1, 2 ), Points( X, Y, Legend( 59 ) ) ),
	Elements( Position( 1, 3 ), Points( X, Y, Legend( 61 ) ) ),
	Elements( Position( 1, 4 ), Points( X, Y, Legend( 63 ) ) ),
	Elements( Position( 1, 5 ), Points( X, Y, Legend( 65 ) ) ),
	Elements( Position( 1, 6 ), Points( X, Y, Legend( 67 ) ) ),
	SendToReport( Dispatch( {}, "graph title", TextEditBox, {Set Text( datasetname )} ) )
);
Craige
lala
Level VII

Re: 怎样将二进制文件中的指定字节转化为浮点数字?

非常感谢专家的帮助!

 

JMP功能太强大了! 

 

JMP原来可以这样使用!

我所懂得的也太少了。

 

再次感谢专家 !

lala
Level VII

Re: 怎样将二进制文件中的指定字节转化为浮点数字?

我还是要继续向专家请教:

如果只从这个文件中提取最后 480行这样的数据、要如何修改代码?

感谢专家!

 

这样的数据在原文件中是 5070 行。而且原始的二进制文件的末尾部分是其它文字、不是数据。