【题外话】

【题外话】

C#中的基础数据类型并不曾放手于c#言语中,而放置于.net freamework.

多年来实验室要自己修改C3D(The 3D Biomechanics Data
斯坦dard)文件,就算从网络找到了三个叫c3d4sharp的类库,这几个类库单纯读取C3D文件的话仍可以够,然则若是要兑现修改或许创建C3D文件就比较麻烦了。同有的时候候c3d4sharp实现得比较简单,许多C3D文件里有个别数据都不援救。万幸C3D文件总体不是很复杂,于是自个儿就从头重新写了三个C3D文件读写的库,今后在codeplex上成立了个类型叫C3D.NET。

近些日子在做C3D文件的深入分析,好古怪的是文本中照旧存款和储蓄了CPU的门类,原来不认为然,结果后来读取多个文本开采浮点数全体读取错误。查了下发掘尽管在上世纪80年份就提出了IEEE754要合并浮点数标准,不过到现行反革命如故有管理器应用不一样方法存款和储蓄浮点数。在少数非IEEE754规范的微型计算机发生的二进制文件中,假若获得任何计算机中读取,借使不实行非常的转变,可能产生数据失实等主题素材。

C#有17个约定义类型,当中12个是值类型,七个是引用类型(string和object)

 

 

一、值类型

【小说索引】

【文章索引】

 

  1. C3D文件格式的布局
  2. C3D文件头的组织
  3. C3D文件参数集合的组织
  4. C3D文件数量区域的构造
  5. 运用C3D.NET读写文件示例
  1. IEEE754标准浮点数字的积攒详解
  2. VAX及IBM浮点数字的仓库储存和调换
  3. 双精度浮点数的管理

值类型

 

 

数据类型

【一、C3D文件格式的布局】

【一、IEEE754标准浮点数字的存储详解】

名称

首先说C3D文件全部不是很复杂,也未有过多复杂的概念,C3D的文书档案格式能够从其官方网站下载或在线阅读。首先C3D文件是以Section为单位存款和储蓄的,每叁个Section固定为512字节。Section一定是按顺序存款和储蓄的,然而有意思的是,Section的序号是从1上马的,而不是0。C3D文件分为三片段,分别是Section
ID = 1的C3D文件头(固定为三个Section,512字节),Section
ID一般等于2(在文书头内会提交)的C3D参数会集以及Section
ID不了然等于几(在文件头和参数集结中都会付给)的C3D数据部分。

对于x86等普及的CPU,都以利用IEEE754存储和测算浮点型的,当然在.NET平新竹浮点型也是IEEE754标准的。首先想起下本科时学过的处理器组成原理,查了下课本开掘是之类介绍IEEE754浮点数的贮存的(唐朔飞版课本233页):

CTS类型

可是C3D也会有很复杂的地方,三个是有关整型的选择,能够使用使用有号子的(Int16),也足以利用无符号的(UInt16),只可是后者能积攒的数据量要多一些而已,既然这样,不知缘何当初还要采纳有号子的整型。而且最主要的是,文书档案内未有别的标志能提出文书档案使用的是何种整型。官方给出的缓和情势是,能够依照举个例子帧总数、帧索引等推断,如果读出负数,则选用无符号的,不然选取有暗记的。

Betway官网 1

说明

另多个是C3D文件能在分歧类型的CPU上调换,那显示于不一样CPU大概使用的字节序(Endian)和浮点数字区别,举例大家用的CPU都以应用Little-Endian以及IEEE754的浮点数标准。从英特网查还发掘有DEC
(VAX)以及IBM等CPU采取不一样的浮点数规范,详见小编以前一篇小说:。而C3D则是永葆3类CPU,英特尔CPU选用Little-Endian以及IEEE754标准的浮点数,DEC
(VAX)选用的Little-Endian以及故意的浮点数,MIPS
(SGI)采纳的Big-Endian以及IEEE754规范的浮点数,所以在读取文书档案的时候或然须求卓殊开始展览管理,在第二节会详细表达。

个中,S为数符,它意味着浮点数的正负,但与其一蹴而就位(尾数)是分离的。阶码用移码表示,阶码的真值都被抬高三个常数(偏移量),如短实数、长实数和有的时候实数的偏移量用十六进制表示分别为7FH、3FFH和3FFFH。尾数部分常见都以规格化表示,即非“0”的实用位最高位三番五次1。

范围

 

以单精度浮点数为例,尽管字节查六柱预测应是之类那个样子的,数符占第1字节的第3位,阶码占第1字节的后7位及第二字节的第3位,其余都以尾数。

  有符号

【二、C3D文件头的布局】

SEF      S        EEEEEEEE        FFFFFFF        FFFFFFFF        FFFFFFFF
bits     1        2      9        10                                    32
bytes    byte1           byte2                   byte3           byte4

    整数

率先来讲第一片段,也正是C3D的公文头,C3D的文件头一定只占1个Section,即定位的512字节,所以一旦读取前512字节就足以把全部头数据获得到了。纵然各种Section有512字节之多,然则对于C3D的公文头只占了相当少的一片段,在文件头中有大气空荡荡的区域。在那之中第一有个别是文本头参数部分,内容如下:

若是设数符为S,阶码为E,尾数的小数部分为F,那么能够经过位运算获得这三位:

sbyte    

Betway官网 2

Double S = (byte1 & 0x80) >> 7;
Double E = ((byte1 & 0x7F) << 1) + ((byte2 & 0x80) >> 7);
Double F = ((byte2 & 0x7F) << 16) + (byte3 << 8) + byte4;

System.Sbyte 

字节 类型 说明
00H Byte 参数集合开始的Section ID(通常为0x02,但也不一定)
01H Byte 文件标识(固定为0x50)
02H-03H Int16 每帧里3D坐标点的个数
04H-05H Int16 每帧里模拟测量的个数
06H-07H Int16 第1帧的序号(最小为1)
08H-09H Int16 最后1帧的序号
0AH-0BH Int16 最大插值差距
0CH-0FH Single 比例因子(正数表示存储的帧为整数帧,负数为浮点帧)
10H-11H Int16  数据区域开始的Section ID
12H-13H Int16 每帧模拟采样个数
14H-17H Single 帧率

是因为阶码用移码表示,所以实际的阶码则是E –
0x7F。而尾数由于是规格化的代表,将要尾数标准成为(1.FFFFF……FF)2,但只存小数点之后的有的。由于1
/ 2 + 1 / 4 + 1 / 8 + … + 1 / n = 1 – 1 /
2n,所以可以尾数M(M = 1.0 + F)的限定为1 <= M <= 2 – 1
/ 223

8位有暗记的寸头

在此之后的第二局地,也正是储存的事件,听起来应该占诸多字节,但是出于限制了事件数量最多不能够超出二十一个,同期事件名称最长为4字节,所以事件部分也只占没多少的空间。由于C3D主若是为了记录运动的数目,恐怕在其间有繁多相比主要的地点,事件正是用来标志出那么些地点的。三个事件包涵四个内容,分别是最长四字节的事件名称、一字节的风云是不是应该出示的情况以及三个四字节的单精度浮点数表示事件出现的时刻。

就此可通过如下的公式来计算浮点数的值,个中,C是尾数标准化后回退的常量,B是移码的偏移量,可见A、B、C分别为A
= 2、B = 0x7F以及C = 1.0。

-128~127(-2^7~2^7-1)

字节 类型 说明
12AH-12BH Int16 事件名是否支持4字节(支持为0x3039,不支持为0)
12CH-12DH Int16 事件数量(最大为18)
130H-176H Single[] 按事件顺序存储的每个事件发生的时间(第1个帧为0.0s)
178H-188H Byte[] 按事件顺序存储的每个事件是否应该显示(1为显示,0为不显示)
18CH-1D2H Char[] 按事件顺序存储的每个事件的名称(每个事件占4字节)
V = (-1)^S * (F + C) * A^(E - B)

short

 

足见,浮点数就不存在0的定义了,所以只好用极端小来代表,同有的时候间为了表示无穷大,规定E取值范围为0
< E < 0xFF,即-0x7F < (E – B) < 0x80。

System.Int16

【三、C3D文件参数会集的构造】 

据此,当E = 0xFF时,指数最大,规定F = 0时为无穷值,在那之中又有S =
0为正无穷以及S = 1为负无穷;而F != 0时为无用数字(NaN)。

十三位有标记的整数

C3D文件存款和储蓄了大气的参数,其行使了看似目录的法子存款和储蓄了参数,可是万幸只有拔尖。即参数部分只有参数组和参数,并且每一个参数组里只可以有参数不可能再包罗参数组,每种参数必须在二个参数组内。参数集结初始于文件头中的率先个字节表示的Section
ID,平时为2,不过也不必然,有的文件会在文件头后留出空白,然后参数集结伊始的Section
ID就延迟了。所以判定是还是不是为C3D文件千万不要一初阶读进去个Int16然后推断是否0x5002,而迟早要咬定第一个字节是或不是0x50,明确参数会集的地点也必然要基于文件的首先字节来。

当E = 0时,指数最小,规定F = 0时为0,在那之中又有S = 0为正0以及S = 1时为-0。

-32768~32767(-2^15~2^15-1)

而对此参数集合,伊始的4字节定义如下:

可是表示丰裕小的数字,允许当E = 0时非标准化的倒数存在。即当E = 0且F
!=0时,V = (-1)^S * F * A^-126。

int

字节 类型 说明
00H Byte 第一个参数所在的Section在整个参数集合中的位置(通常为0x01,说明开头4字节之后就是第一个参数)
01H Byte 参数集合部分标识(固定为0x50)
02H Byte 参数集合所占Section数量
03H Byte 生成文件的CPU类型(0x54为Intel,0x55为DEC (VAX, PDP-11),0x56为MIPS (SGI/MIPS))
二进制表示 十六进制表示 含义 十进制表示
0 11111111 00000000000000000000000 7F 80 00 00 正无穷 +∞ 
1 11111111 00000000000000000000000 FF 80 00 00 负无穷 -∞ 
0 00000000 00000000000000000000000 00 00 00 00 +0 0
1 00000000 00000000000000000000000 80 00 00 00 -0 0
0 00000000 00000000000000000000001 00 00 00 01  最小正数  1.401298E-45
0 11111110 11111111111111111111111 7F 7F FF FF 最大值 3.402823E+38
1 11111110 11111111111111111111111 FF 7F FF FF 最小值 -3.402823E+38
0 01111111 00000000000000000000000 3F 80 00 00 +1 1

System.Int32

当中前2个字节官方说平昔忽略就行,可是为了同盟在写入的时候依旧要写进去的。第3字节其实大家按梯次读到头也不供给那么些数额。那中间主要的是CPU类型,由于分化CPU类型选取的字节序以及存款和储蓄的浮点数字有所分化,所以大家还亟需基于CPU类型举行相应的拍卖。

而二进制小数转十进制小数的一个钱打二十五个结能够一贯按整数的更改成做,然后除以2n就能够,n在那边其实便是尾数的长度,为23。

叁十四人有号子的卡尺头

对此速龙和DEC生成的文书档案,都以运用Little-Endian字节序存款和储蓄的文书档案,所以必然要动用Little-Endian来读取Int16、Single等连串;而MIPS则使用的Big-Endian字节序存储文书档案,所以在读取的时候自然要看清当前计算机暗中认可的字节序以及文书档案选择的字节序。

就此,有了以上的这几个信息,我们就足以将浮点数字与字节数组互相调换了(本文假定给定的字节数组都以Litten-Endian):

-2147483648~2147483647(-2^31~2^31-1)

而对于英特尔和MIPS生成的文书档案,对于浮点数字的存款和储蓄都是行使标准的IEEE754浮点数字,对于.NET来说无需开始展览任何管理;而DEC生成的文书档案则利用特有浮点数,需求将4个字节全部读取今后再张开特殊的转移,调换方法见小编前边的篇章:。

 1 Single ToSingle(Byte[] data)
 2 {
 3     Double a = 2.0;
 4     Double b = 127.0;
 5     Double c = 1.0;
 6     Double d = -126.0;
 7 
 8     Byte byte1 = data[3];
 9     Byte byte2 = data[2];
10     Byte byte3 = data[1];
11     Byte byte4 = data[0];
12 
13     Double s = (byte1 & 0x80) >> 7;
14     Double e = ((byte1 & 0x7F) << 1) + ((byte2 & 0x80) >> 7);
15     Double f = ((byte2 & 0x7F) << 16) + (byte3 << 8) + byte4;
16     Double m = f / Math.Pow(2, 23);
17 
18     if (e == 0xFF && f == 0) return (s == 0 ? Single.PositiveInfinity : Single.NegativeInfinity);
19     if (e == 0xFF && f != 0) return Single.NaN;
20     if (e == 0x00 && f == 0) return 0;
21     if (e == 0x00 && f != 0) return (Single)((s == 0 ? 1.0 : -1.0) * m * Math.Pow(a, d));
22 
23     return (Single)((s == 0 ? 1.0 : -1.0) * (c + m) * Math.Pow(a, e - b));
24 }
25 
26 Byte[] GetBytes(Single num)
27 {
28     Double a = 2.0;
29     Double b = 127.0;
30     Double c = 1.0;
31     Double d = Math.Log(2);
32 
33     Int32 s = (num >= 0 ? 0 : 1);
34 
35     Double v = Math.Abs(num);
36     Int32 e = (Int32)(Math.Log(v) / d + b);
37 
38     Double m = (v / Math.Pow(a, e - b)) - c;
39     Int32 f = (Int32)(m * Math.Pow(2, 23));
40 
41     Byte[] data = new Byte[4];
42     data[3] = (Byte)((s << 7) + ((e & 0xFE) >> 1));
43     data[2] = (Byte)(((e & 0x01) << 7) + ((f & 0x007F0000) >> 16));
44     data[1] = (Byte)((f & 0x0000FF00) >> 8);
45     data[0] = (Byte)(f & 0x000000FF);
46 
47     return data;
48 }

long

在此之下就存款和储蓄着独具的参数了,参数分为两类,分别是参数组和参数。

上述的浮点数转字节数组不可能支撑NaN和非标准化的事态,当然也能够自身看清下。当然了,上边说了那样多仍旧为了介绍上面三种浮点数做铺垫。假如达成系统浮点数与字节数组转变的话,用下面这种格局调换就不及用System.BitConverter来的方便人民群众了。

System.Int64

对于参数组,要存款和储蓄以下6个内容:

 

62人有号子的平头

字节 类型 说明
00H SByte 参数组名称长度(如果为负数则表示该参数组锁定请不要修改,而长度为绝对值)
01H SByte 参数组ID的负数
02H – … Char[] 参数组名称(仅包含大写字母、0-9以及下划线_)
… + 1 – … + 2 Int16 下一参数组/参数的偏移(包含本内容的2字节)
… + 3 Byte 参数组描述长度
… + 4 –  Char[] 参数组描述内容(ASCII码)

【二、VAX及IBM浮点数字的蕴藏和改变】

-2^63~2^63-1

C3D文件未有规定贰个参数组前边跟另三个参数组照旧跟该参数组里的富有参数,所以读取的时候要留意下。而参数的剧情则与参数组基本同样,只是在下一参数组/参数的摇晃与参数组描述长度之间存放着该参数的莫过于数目罢了,由于地方描述起来太费事了,这里就不写了。

首先照旧按字节看下VAX和IBM浮点型的蕴藏:

无符号整数

字节

VAX单精度浮点:

byte

类型

SEF         S        EEEEEEEE        FFFFFFF        FFFFFFFF        FFFFFFFF
bits        1        2      9        10                                    32
bytes       byte2           byte3                   byte0           byte1

System.Byte

说明

IBM单精度浮点:

8位无符号的子弹头

事先的内容

SEF         S        EEEEEEE        FFFFFFFF        FFFFFFFF        FFFFFFFF
bits        1        2     8        9                                      32
bytes       byte1                   byte2           byte3           byte4

0~255(0~2^8-1)

 

老大有意思的是,VAX存款和储蓄的构造并不是按顺序存款和储蓄的,而是采纳了一种名字为Middle-Endian的存款和储蓄格局来积攒(并非字节序):对于四字节来讲其顺序正是2301,八字节为23016745,十六字节为23016745AB89EFCD。不过全体来讲,VAX浮点型与IEEE754照旧很周边的,比方VAX也要开始展览规范化,不过其专门的工作成为(0.1FFFFF..FF)2,所以上述的C就为0.5,其尾数M的限量即为三分一<= M <= 1 – 1 /
224;而还要其也并从未规定无穷大,无需单独为极端大留出最大的阶码,所以上述的B为0x80。

ushort

Int16

而IBM单精度浮点则与上述三种差别越来越大。首先其阶码并不是8位,而是7位,由于还是选取移码存款和储蓄的阶码,所以其缩减的无法是127要么128,而是64,所以其与VAX同样,也并未有无穷值的代表。除此而外,其也不是以2为底总括阶码的,而是以16为底,并且其并未有标准化尾数的渴求(当然这也与其以16为底有关),所以无需对倒数进行加减运算,其范围为1/16
<= M <= 1- 1 / 224

System.UInt16

下一参数组/参数的偏移(包蕴本内容的2字节)

以下是落实VAX浮点字节数组与系统浮点数字互相转化的类:

十八位无符号的整数

 

Betway官网 3Betway官网 4

0~2^16-1

Byte

 1 using System;
 2 
 3 namespace DotMaysWind.Numerics
 4 {
 5     /// <summary>
 6     /// VAX单精度浮点数字
 7     /// </summary>
 8     /// <remarks>
 9     /// SEF         S        EEEEEEEE        FFFFFFF        FFFFFFFF        FFFFFFFF
10     /// bits        1        2      9        10                                    32          
11     /// bytes       byte2           byte1                   byte4           byte3
12     /// </remarks>
13     public struct VAXSingle
14     {
15         #region 常量
16         private const Int32 LENGTH = 4;
17         private const Double BASE = 2.0;
18         private const Double EXPONENT_BIAS = 128.0;
19         private const Double MANTISSA_CONSTANT = 0.5;
20         private const Double E24 = 16777216.0;
21         #endregion
22 
23         #region 字段
24         private Byte[] _data;
25         #endregion
26 
27         #region 构造方法
28         /// <summary>
29         /// 初始化新的VAX单精度浮点数字
30         /// </summary>
31         /// <param name="data">VAX单精度浮点数字字节数组</param>
32         /// <param name="startIndex">数据起始位置</param>
33         public VAXSingle(Byte[] data, Int32 startIndex)
34         {
35             this._data = new Byte[VAXSingle.LENGTH];
36             Array.Copy(data, startIndex, this._data, 0, VAXSingle.LENGTH);
37         }
38 
39         /// <summary>
40         /// 初始化新的VAX单精度浮点数字
41         /// </summary>
42         /// <param name="num">系统标准的单精度浮点数字</param>
43         public VAXSingle(Single num)
44         {
45             Int32 s = (num >= 0 ? 0 : 1);
46 
47             Double v = Math.Abs(num);
48             Int32 e = (Int32)(Math.Log(v) / Math.Log(2.0) + 1.0 + VAXSingle.EXPONENT_BIAS);
49 
50             Double m = (v / Math.Pow(VAXSingle.BASE, e - VAXSingle.EXPONENT_BIAS)) - VAXSingle.MANTISSA_CONSTANT;
51             Int32 f = (Int32)(m * VAXSingle.E24);
52 
53             this._data = new Byte[VAXSingle.LENGTH];
54             this._data[1] = (Byte)((s << 7) + ((e & 0xFE) >> 1));
55             this._data[0] = (Byte)(((e & 0x01) << 7) + ((f & 0x007F0000) >> 16));
56             this._data[3] = (Byte)((f & 0x0000FF00) >> 8);
57             this._data[2] = (Byte)(f & 0x000000FF);
58         }
59         #endregion
60 
61         #region 方法
62         /// <summary>
63         /// 获取系统标准的单精度浮点数字
64         /// </summary>
65         /// <returns>系统标准的单精度浮点数字</returns>
66         public Single ToSingle()
67         {
68             Byte b1 = this._data[1];
69             Byte b2 = this._data[0];
70             Byte b3 = this._data[3];
71             Byte b4 = this._data[2];
72 
73             Double s = (b1 & 0x80) >> 7;
74             Double e = ((b1 & 0x7F) << 1) + ((b2 & 0x80) >> 7);
75             Double f = ((b2 & 0x7F) << 16) + (b3 << 8) + b4;
76             Double m = f / VAXSingle.E24;
77 
78             if (e == 0 && s == 0) return 0;
79             if (e == 0 && s == 1) return Single.NaN;
80 
81             return (Single)((s == 0 ? 1.0 : -1.0) * (VAXSingle.MANTISSA_CONSTANT + m) * Math.Pow(VAXSingle.BASE, e - VAXSingle.EXPONENT_BIAS));
82         }
83 
84         /// <summary>
85         /// 获取VAX单精度浮点数据字节数组
86         /// </summary>
87         /// <returns>字节数组</returns>
88         public Byte[] ToArray()
89         {
90             Byte[] data = new Byte[VAXSingle.LENGTH];
91 
92             Array.Copy(this._data, data, VAXSingle.LENGTH);
93 
94             return data;
95         }
96         #endregion
97     }
98 }

uint

参数存放内容的类型(-1 Char,1 Byte,2
Int16,4 Single),相对值即为长度

View Code

System.UInt36

 

以下是完毕IBM浮点字节数组与系统浮点数字相互转化的类:

叁10位无符号的整数

Byte

Betway官网 5Betway官网 6

0~2^32-1

参数内容维数(0-3)

 1 using System;
 2 
 3 namespace DotMaysWind.Numerics
 4 {
 5     /// <summary>
 6     /// IBM单精度浮点数字
 7     /// </summary>
 8     /// <remarks>
 9     /// SEF         S        EEEEEEE        FFFFFFFF        FFFFFFFF        FFFFFFFF
10     /// bits        1        2     8        9                                      32
11     /// bytes       byte1                   byte2           byte3           byte4
12     /// </remarks>
13     public struct IBMSingle
14     {
15         #region 常量
16         private const Int32 LENGTH = 4;
17         private const Double BASE = 16.0;
18         private const Double EXPONENT_BIAS = 64.0;
19         private const Double E24 = 16777216.0;
20         #endregion
21 
22         #region 字段
23         private Byte[] _data;
24         #endregion
25 
26         #region 构造方法
27         /// <summary>
28         /// 初始化新的IBM单精度浮点数字
29         /// </summary>
30         /// <param name="data">IBM单精度浮点数字字节数组</param>
31         /// <param name="startIndex">数据起始位置</param>
32         public IBMSingle(Byte[] data, Int32 startIndex)
33         {
34             this._data = new Byte[IBMSingle.LENGTH];
35             Array.Copy(data, startIndex, this._data, 0, IBMSingle.LENGTH);
36         }
37 
38         /// <summary>
39         /// 初始化新的IBM单精度浮点数字
40         /// </summary>
41         /// <param name="num">系统标准的单精度浮点数字</param>
42         public IBMSingle(Single num)
43         {
44             Int32 s = (num >= 0 ? 0 : 1);
45 
46             Double v = Math.Abs(num);
47             Int32 e = (Int32)(Math.Log(v) / Math.Log(2.0) / 4.0 + 1.0 + IBMSingle.EXPONENT_BIAS);
48 
49             Double m = (v / Math.Pow(IBMSingle.BASE, e - IBMSingle.EXPONENT_BIAS));
50             Int32 f = (Int32)(m * IBMSingle.E24);
51 
52             this._data = new Byte[IBMSingle.LENGTH];
53             this._data[3] = (Byte)(s + e);
54             this._data[2] = (Byte)((f & 0x00FF0000) >> 16);
55             this._data[1] = (Byte)((f & 0x0000FF00) >> 8);
56             this._data[0] = (Byte)(f & 0x000000FF);
57         }
58         #endregion
59 
60         #region 方法
61         /// <summary>
62         /// 获取系统标准的单精度浮点数字
63         /// </summary>
64         /// <returns>系统标准的单精度浮点数字</returns>
65         public Single ToSingle()
66         {
67             Byte b1 = this._data[3];
68             Byte b2 = this._data[2];
69             Byte b3 = this._data[1];
70             Byte b4 = this._data[0];
71 
72             Double s = (b1 & 0x80) >> 7;
73             Double e = (b1 & 0x7F);
74             Double f = (b2 << 16) + (b3 << 8) + b4;
75             Double m = f / IBMSingle.E24;
76 
77             if (e == 0 && f == 0 && s == 0) return 0;
78 
79             return (Single)((s == 0 ? 1.0 : -1.0) * m * Math.Pow(IBMSingle.BASE, e - IBMSingle.EXPONENT_BIAS));
80         }
81 
82         /// <summary>
83         /// 获取IBM单精度浮点数据字节数组
84         /// </summary>
85         /// <returns>字节数组</returns>
86         public Byte[] ToArray()
87         {
88             Byte[] data = new Byte[IBMSingle.LENGTH];
89 
90             Array.Copy(this._data, data, IBMSingle.LENGTH);
91 
92             return data;
93         }
94         #endregion
95     }
96 }

ulong

 

View Code

System.UInt66

Byte[]

 

陆十位无符号的大背头

参数每一维大小(若是维数为0,就未有此部分)

【三、双精度浮点数的管理】

0~2^64-1

 

双精度浮点数与单精度浮点数类似,只但是会扩张阶码和倒数的限制罢了。对于IEEE754的双精度浮点来讲,不止倒数的位数增添,还有或许会追加阶码的尾数,字节存款和储蓄如下:

 

Byte[] 

SEF    S     EEEEEEE EEEE  FFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
bits   1     2          12 13                                                       64
bytes  byte1         byte2      byte3    byte4    byte5    byte6    byte7    byte8

值类型

参数实际内容

可知,其阶码扩张了3位,即最大值是原先翻了3翻,为1024。而为了保障能代表无穷值,所以B为1023。除了这一个之外只需求多读取前面扩展的尾数就能够,步骤与单精度基本一样。

数据类型

 

而对此VAX和IBM的双精度浮点,更是未有增添阶码的界定,而只是扩展了倒数的限制,使得只要多读取扩大的4位尾数就能够,而常数A、B、C更是没有必要修改。两个字节存款和储蓄如下:

名称

Byte

VAX双精度浮点:

CTS类型

参数组描述长度

SEF    S     EEEEEEEE     FFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
bits   1     2      9     10                                                          64
bytes  byte2        byte3         byte0    byte1    byte6    byte7    byte4    byte5

说明

今后的剧情

IBM双精度浮点:

范围

这里要求表达的正是,由于参数能够存放数组,所以扩充了维数的标记,即当维数为0时,存放的原委为Char、Byte、Int16、Single等转移出的字节数组;而当维数为1时,存放的为Char[]、Byte[]、Int16[]、Single[]等转移出的字节数组,依此类推。而对数组的积攒,其实就是数组每一种成分依次展展开酒店储,而对此多维数组,则是按行优先开始展览仓库储存的,比如三个维度数组,先存款和储蓄Data[0,0,1]再存储Data[0,0,2],依次类推。

SEF    S     EEEEEEE  FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
bits   1     2     8  9                                                            64
bytes  byte1          byte2    byte3    byte4    byte5    byte6    byte7    byte8

 浮点数

唯独需求注明的是,对于Char[]以及Char[,]这二种,假使表示的话实际应当相应的是String以及String[]。

 

decimal

 

【相关链接】

System.Decimal

【四、C3D文件数量区域的协会】

  1. Transform between IEEE, IBM or VAX floating point number formats and
    bytes
    expressions:
  2. VAX F_FLOAT and D_FLOAT to IEEE T_FLOAT and S_FLOAT
    (double):
  3. IEEE
    Arithmetic:
  4. Floating-Point:
  5. IBM Floating Point
    Architecture:
  6. VAX floating point to
    Decimal:

1二十六个人高精度十进制数表示法

C3D数据区域以帧为单位寄放的,其实一定于那一个区域正是一个帧的成团。而C3D帧其实分为二种,一种是整数帧,而另一种是浮点帧。那二者的分别在于,前者存款和储蓄的具有内容都以Int16,而后者则为Single,除却,前者的3D坐标点(X、Y、Z)还索要倍Gaby例因子才得以,而后者存款和储蓄的内容相当于已经乘以了百分比因子了。

正 79,228,162,514,264,337,593,543,950,335 到负 79,228,162,514,264,337,593,543,950,335 之间的十进制数

数码区域初始于参数集结中的”POINT”参数组中的”DATA_START”参数,其象征数据区域初阶的Section
ID,除了这几个之外,在文书头中也可以有一份别本。然而遵照法定的说教,要是文件头和参数集结中都一些内容,优先读取参数集合中的数据。

float

对此每一种帧,又包蕴五个部分,第一片段为3D坐标点部分,第二部分为参照他事他说加以考察采集样品部分。

System.Single

  • 对于每帧的3D坐标点部分,存储着该帧全部3D坐标点的数量,每一种3D坐标点包含4个Int16或Single数据,分别是X坐标、Y坐标、Z坐标以及Residual和Camera
    Mask,个中Residual和Camera
    Mask共占八个Int16。相比较有趣的是,对于浮点帧,Residual和Camera
    Mask依然也依旧贰个Int16,只可是存款和储蓄的时候要将相应的数值转换为Single再实行仓库储存。

    • 对于浮点帧,存储的X、Y、Z坐标便是其实的坐标;而对此整数帧,存款和储蓄的X、Y、Z的坐标还要求倍Gaby例因子才具够,比例因子存款和储蓄于参数会集中的”POINT”参数组中的”SCALE”参数。
    • Residual和Camera
      Mask共占多个Int16,将其转移为字节数组之后,高位字节(第2个字节)的万丈位表示Residual的符号,即意味着该坐标点是还是不是行得通,假设为0则代表有效,假使为1则意味着无效,而剩下的7个字节则为Camera
      Mask,每一人表示贰个版画机,从未有到高位分别代表7个录制机是不是选用(为1为利用,为0为未接纳)。而Residual的实际数据则为字节数组的第0字节乘以比例因子(浮点帧则为比例因子的相对值)。
  • 而仿照采集样品部分,则存款和储蓄着该帧全数的一成不改变采集样品的数额,然则每种帧只怕包罗多少个模拟采集样品,同时各个模仿采集样品也许又含有七个channel,存款和储蓄的数目即为该channel下记录的数码。可是存款和储蓄的数额与实际的数额还索要依赖下述公式实行折算,个中data
    value为存款和储蓄的数据,real world value为实际的数量。

    • zero
      offset能够从”ANALOG”参数组中的”OFFSET”中赢得,该数量为Int16的数组,第i位指的正是第i个channel的zero
      offset。
    • channel
      scale能够从”ANALOG”参数组中的”SCALE”中拿走,该多少为Single的数组,第i位指的便是dii个channel的scale。
    • general
      scale是全体模拟采集样品都急需倍加的比重,该数据能够从”ANALOG”参数组中的”GEN_SCALE”中获取,为Single。

    real world value = (data value – zero offset) channel scale general scale

叁十二个人单精度浮点

 

(-3.402823e38 ~ +3.402823e38)

【五、使用C3D.NET读写文件示例】

double

前方说了如此多,其实假如用C3D.NET来解析的话实际是特别轻松的。我们能够从下载C3D.NET的二进制文件大概源码,援引后根本的类都在C3D那个命名空间下。

System.Double

对此遍历全数的3D坐标能够行使以下的方法,首先能够从文件可能从流中创制C3D文件,然后从文件头中读取存款和储蓄的第1帧的序号,然后读取采集样品点的多少就能够了,当然也得以不从参数组中读取,直接采纳file.AllFrames[i].Point3Ds.Length也可以:

双精度 64 位数字

 1 C3DFile file = C3DFile.LoadFromFile("文件路径");
 2 Int16 firstFrameIndex = file.Header.FirstFrameIndex;
 3 Int16 pointCount = file.Parameters["POINT:USED"].GetData<Int16>();
 4 
 5 for (Int16 i = 0; i < file.AllFrames.Count; i++)
 6 {
 7     for (Int16 j = 0; j < pointCount; j++)
 8     {
 9         Console.WriteLine("Frame {0} : X = {1}, Y = {2}, Z = {3}",
10             firstFrameIndex + i,
11             file.AllFrames[i].Point3Ds[j].X,
12             file.AllFrames[i].Point3Ds[j].Y ,
13             file.AllFrames[i].Point3Ds[j].Z);
14     }
15 }

( -1.79769313486232e308 ~ 1.79769313486232e308)

而读取模拟采集样品的话,选用的点子也近乎:

 

 1 Single frameRate = file.Parameters["POINT", "RATE"].GetData<Single>();
 2 Int16 analogChannelCount = file.Parameters["ANALOG", "USED"].GetData<Int16>();
 3 Int16 analogSamplesPerFrame = (Int16)(file.Parameters["ANALOG", "RATE"].GetData<Int16>() / frameRate);
 4 
 5 for (Int16 i = 0; i < file.AllFrames.Count; i++)
 6 {
 7     for (Int16 j = 0; j < analogChannelCount; j++)
 8     {
 9         for (Int16 k = 0; k < analogSamplesPerFrame; k++)
10         {
11             Console.WriteLine("Frame {0}, Sample {1} : {2}",
12                 firstFrameIndex + i, j + 1,
13                 file.AllFrames[i].AnalogSamples[j][k]);
14         }
15     }
16 }

 

除却一次性将C3D文件内容总体读抽出来的这种措施以外,还是能够利用C3DReader来一帧一帧的读取。

值类型

 1 using (FileStream fs = new FileStream("文件路径", FileMode.Open, FileAccess.Read))
 2 {
 3     C3DReader reader = new C3DReader(fs);
 4     C3DHeader header = reader.ReadHeader();
 5     C3DParameterDictionary dictionary = reader.ReadParameters();
 6     Int32 index = header.FirstFrameIndex;
 7 
 8     while (true)
 9     {
10         C3DFrame frame = reader.ReadNextFrame(dictionary);
11 
12         if (frame == null)
13         {
14             break;
15         }
16 
17         for (Int16 j = 0; j < frame.Point3Ds.Length; j++)
18         {
19             Console.WriteLine("Frame {0} : X = {1}, Y = {2}, Z = {3}",
20                 index++,
21                 frame.Point3Ds[j].X,
22                 frame.Point3Ds[j].Y,
23                 frame.Point3Ds[j].Z);
24         }
25     }
26 }

数据类型

对于开创一个C3D文件,只必要动用C3DFile.Create()就可以创设贰个空的C3D文件的,不包括别的的参数集结。而保存C3D文件则直接选取file.SaveTo(“文件路线”)就能够了。

名称

对于增加参数集合能够利用以下的代码:

CTS类型

1 //首先需要添加参数集合,ID为正数
2 file.Parameters.AddGroup(1, "POINT", "");
3 //然后往指定ID的参数集合中添加参数即可
4 file.Parameters[1].Add("USED", "").SetData<Int16>(5);

说明

加多帧能够动用如下的代码:

范围

1 file.AllFrames.Add(new C3DFrame(new C3DPoint3DData[] {
2     new C3DPoint3DData() { X = x, Y = y, Z = z, Residual = residual, CameraMask = cameraMask},
3     new C3DPoint3DData() { X = x, Y = y, Z = z, Residual = residual, CameraMask = cameraMask},
4     new C3DPoint3DData() { X = x, Y = y, Z = z, Residual = residual, CameraMask = cameraMask},
5     new C3DPoint3DData() { X = x, Y = y, Z = z, Residual = residual, CameraMask = cameraMask},
6     new C3DPoint3DData() { X = x, Y = y, Z = z, Residual = residual, CameraMask = cameraMask} }));

  字符

本来,也得以将C3DPoint3DData数组换来C3DAnalog萨姆ples数组,或然双方同期丰硕也能够。

char   

 

System.Char

【相关链接】

代表四个十多少人的(Unicode)字符

  1. C3D.ORG:
  2. c3d4sharp – C3D File reading/writing tools written in
    C#:
  3. C3D.NET:

U+0000 到 U+FFFF

 

 

二、援用类型

 

援引类型

数据类型

名称

CTS类型

说明

范围

引用   类型

object

System.Object

不无类型的基类

支撑具有品类的装箱和拆箱

string

System.String

字符串

零个或越来越多 Unicode 字符

 

代码简单演示 范围

 

//整形 
            sbyte sbyteMin = -128;
            sbyte sbyteMax = 127;

            short shortMin = -32768;
            short shortMax = 32767;

            int intMin = -2147483648;
            int intMax = 2147483647;

            long longMin = -9223372036854775808;
            long longMax = 9223372036854775807;

            byte byteMin = 0;
            byte byteMax = 255;

            ushort ushortMin = 0;
            ushort ushortMax = 65535;

            uint uintMin = 0;
            uint uintMax = 4294967295;

            ulong ulongMin = 0;
            ulong ulongMax = 18446744073709551615;

            //浮点型
            decimal decimalMin = -79228162514264337593543950335M;
            decimal decimalMax = 79228162514264337593543950335M;
            decimal decimaldianMin = -0.000000000000000000000000001M;
            decimal decimaldianMax = 0.000000000000000000000000001M;

            float floatMin = -3.402823E+38f;
            float floatMax = 3.402823E+38f; 
            float floata = 1111111111111111111111111111111111.111111111111111111111111111111111111111111111111111111f;

            double doubleMin = -1.7976931348623157E+308;
            double doubleMax = 1.7976931348623157E+308;
            //字符型
            char[] chars = new char[4];

            chars[0] = 'X';        // Character literal 字母
            chars[1] = '\x0058';   // Hexadecimal   十六进制
            chars[2] = (char)88;   // Cast from integral type
            chars[3] = '\u0058';   // Unicode 

            foreach (char c in chars)
            {
                Console.Write(c + " ");
            }

            //引用类型
            string stringval = "123123asdasdasdasdjaskdja!@#!@#!@%!dsafsmdfklaskdl;f";

            //引用类型 万能容器
            object obj = "asdasd";
            obj = 1;
            obj = 1.1f;
            obj = 1.1;
            obj = 'a';

 

个人学习脑残总计:

     
这么多类型你用上了哪两种?分别那一个情形选择,还索要遇上相应场景去具体回复。例如一时你知道您的for循环的次数你还会有必要采用int么,举例你通晓你的那些字段不大概是负数的整数你有必不可缺选拔有暗记整数么。程序的优化不是去优化多少个要命大的地方如此的难题一般不广泛而是要去注意九十多个地点的小细节。

decimal
 是挤占位数(128)最大的浮点数取值范围却是最小的在精度需求不高的企图中动用
float  double ,不过在精工细作总计中诸如财务总计中decimal 就比较吻合了
不过decimal 依旧是浮点数所以依旧有精度丢失的标题

         double dd1 = 10000000000000000000000d;
            Console.WriteLine("{0:G50}", dd1);   
            dd1= dd1 +1;
            Console.WriteLine("{0:G50}", dd1);
            decimal dd = 10000000000000000000000000000m;
            dd += 0.1m;
            Console.WriteLine("{0:G50}", dd);  

 

 互联网补充(来源网络)

SQL Server 2000

C#

CodeSmith

数据类型

取值范围

数据类型

取值范围

空值代替值

数据类型

bigint

-2^63 (-9,223,372,036,854,775,807) 至 2^63-1 (9,223,372,036,854,775,807)

Int64

-9,223,372,036,854,775,808;即十六进制的 0x柒仟000000000000至9,223,372,036,854,775,807;即十六进制的 0x7FFFFFFFFFFFFFFF

Int64.MinValue

Int64

binary

原则性长度的 n 个字节二进制数据。N 必须从 1 到 8,000。存款和储蓄空间尺寸为 n+4 字节。

Byte[]

 

null

Binary

bit

True,False

enum

0,1,-1(使用贰个枚举变量来替代)

-1

Boolean

public enum bitNull  

{

    False,

    True,

    Null = -1

};

char

长度为 n 个字节的永久长度且非 Unicode 的字符数据。n 必须是叁个在乎 1 和 8,000 之间的数值。存款和储蓄大小为 n 个字节。

string

 

null

AnsiStringFixedLength

datetime

存款和储蓄从 1753 年 1 月 1 日至 9999 年 12 月 31 日的日子(各类数值供给8 个字节的蕴藏空间)

DateTime

0001 年 1 月 1 日 00:00:00 .0000000至9999 年 12 月 31 日 23:59:59.9999999

1753-01-01 0:00:00

DateTime

decimal

从 – 10^38 +1 到 10^38 – 1

Decimal

-79,228,162,514,264,337,593,543,950,335至79,228,162,514,264,337,593,543,950,335

Decimal.MinValue

Decimal

float

从 – 1.79E + 308 到 1.79E + 308 之间的浮点数字数据

Double

-1.79769313486232e308至+1.79769313486232e308

Double.MinValue

Double

image

可变长度二进制数据在于 0 与 231-1 (2,147,483,647) 字节以内。

Byte[]

 

null

Binary

int

从 -2^31 (-2,147,483,648) 到 2^31 – 1 (2,147,483,647) 的整型数据(全数数字)

int

-2,147,483,648 到 2,147,483,647

-2147483648

Int32

money

通货数据值介于 -2^63 (-922,337,203,685,477.5808) 与 2^63 – 1 (+922,337,203,685,477.5807) 之间,正确到货币单位的千分之十。存款和储蓄大小为 8 个字节。

Single

-3.402823e38至+3.402823e38

Single.MinValue

Currency

nchar

至多为 4000 个 Unicode 字符

string

 

null

StringFixedLength

ntext

可变长度 Unicode 数据的最大尺寸为230 – 1 (1,073,741,823) 个字符。存储大小是所输入字符个数的两倍(以字节为单位)。

string

 

null

String

numeric

选择最大精度时,有效值从 – 10^38 +1 到 10^38 – 1

Decimal

-79,228,162,514,264,337,593,543,950,335至79,228,162,514,264,337,593,543,950,335

Decimal.MinValue

Decimal

nvarchar

富含 n 个字符的可变长度 Unicode 字符数量。n 的值必须介于 1 与 4,000 之间。

string

 

null

String

real

从 ?3.40E + 38 到 3.40E + 38 之间的浮点数字数据。存款和储蓄大小为 4 字节。

Single

-3.402823e38至+3.402823e38

Single.MinValue

Single

smalldatetime

从 壹玖零伍 年 1 月 1 日至 2079 年 6 月 6 日的日子(各样数值供给 4 个字节的积累空间)。

DateTime

0001 年 1 月 1 日 00:00:00 .0000000至9999 年 12 月 31 日 23:59:59.9999999

1900/1/1 0:00

DateTime

smallint

从 -2^15 (-32,768) 到 2^15 – 1 (32,767) 的整型数据。存款和储蓄大小为 2个字节。

Int16

-32768至32767

Int16.MinValue

Int16

smallmoney

通货数据值介于 -214,748.3648 与 +214.748,3647 之间,正确到货币单位的千分之十。存款和储蓄大小为 4 个字节。

Single

-3.402823e38至+3.402823e38

Single.MinValue

Currency

sql_variant

在SQL Server 3000中不帮助大数据类型text, ntext, image, timestamp,别的品种均协理

Object

 

null

Object

text

服务器代码页中的可变长度非 Unicode 数据的最大尺寸为 231-1 (2,147,483,647) 个字符。当服务器代码页使用双字节字符时,存款和储蓄量仍是 2,147,483,647 字节。存款和储蓄大小大概低于 2,147,483,647 字节(取决于字符串)。

string

 

null

AnsiString

timestamp

timestamp 这种数据类型表现自动生成的二进制数,确认保证那几个数在数据库中是有一无二的。timestamp 一般作为给表行加版本戳的建制。存款和储蓄大小为 8字节。

Byte[]

 

null

Binary

tinyint

从 0 到 255 的整型数据。存储大小为1 字节。

Byte

0至255

Byte.MinValue

Byte

uniqueidentifier

积累 16 字节的二进制值,该值的行使与全局唯一标记符 (GUID) 同样。GUID 是四个唯一的二进制数字;世界上的其他两台微型Computer都不会扭转重复的 GUID 值。GUID 首要用来在装有多少个节点、多台Computer的网络中,分配必须具备唯一性的标志符。

Guid

 

Guid.Empty

Guid

varbinary

n 个字节变长二进制数据。n 必须从 1到 8,000。存款和储蓄空间大小为实际输入数据长度 +4 个字节,而不是 n 个字节。输入的数码长度大概为 0 字节。

Byte[]

 

null

Binary

varchar

长度为 n 个字节的可变长度且非 Unicode 的字符数据。n 必须是二个在乎 1 和 8,000 之间的数值。存储大小为输入数据的字节的实际尺寸,而不是 n个字节。所输入的数额字符长度可认为零。

string

 

null

AnsiString

 

c#基础项目XLS

相关文章