精度转换
二进制精度舍入规则
在了解不同类型之间的精度转换规则之前,需先了解二进制的精度舍入规则。
如下图所示,一个二进制数的尾部若干位可能因目标精度不足而被丢弃,这部分称为待舍入部分;剩余保留的部分称为非舍入部分。根据待舍入部分的值以及所选的精度舍入模式,决定非舍入部分的末位是否需要 +1(进位)。
图1 二进制精度舍入规则示意图

各精度舍入模式对待舍入部分的判断规则如下表所示:
| 模式 | 描述 |
|---|---|
| CAST_NONE | 当转换过程存在精度损失时,按CAST_RINT模式处理;当不存在精度损失时,不进行舍入。 |
| CAST_RINT | 向最近的偶数舍入。 •若待舍入部分的首位为0,则不进位。 •若待舍入部分的首位为1且后续位不全为0,则进位。 •若待舍入部分的首位为1且后续位全为0:当非舍入部分的末位为0,则不进位;当非舍入部分的末位为1,则进位。 |
| CAST_FLOOR | 向负无穷大方向舍入。 •若符号位(S)为0(正数),则不进位。 •若符号位(S)为1(负数):当待舍入部分全为0,则不进位;否则,进位。 |
| CAST_CEIL | 向正无穷大方向舍入。 •若符号位(S)为1(负数),则不进位。 •若符号位(S)为0(正数):当待舍入部分全为0,则不进位;否则,进位。 |
| CAST_ROUND | 四舍五入。若待舍入部分的首位为0,则不进位;否则,进位。 |
| CAST_TRUNC | 截断模式。直接丢弃待舍入部分。 |
| CAST_ODD | 向最近的奇数舍入。 •若待舍入部分全为0,则不进位。 •若待舍入部分不全为0:非舍入部分的末位为1,则不进位;当非舍入部分的末位为0,则进位。 |
| CAST_HYBRID | 随机舍入,目前特指输出结果是hifloat8_t数据类型时,会用到的一种随机舍入。 |
精度转换规则
本节主要对不同数据类型之间精度转换时的舍入行为进行介绍。不同数据类型的表示方式请参考内置数据类型。当源值超出目标类型的表示范围时溢出,溢出默认按照饱和模式处理。
int4b_t → int16_t
将源值以int16_t格式存入目的操作数中,无精度损失。
示例:输入:1,输出:1。
int4b_t → half
将源值以half格式存入目的操作数中,无精度损失。
示例:输入:1,输出:1.0。
int4b_t → bfloat16_t
将源值以bfloat16_t格式存入目的操作数中,无精度损失。
示例:输入:1,输出:1.0。
int8_t → half
将源值以half格式存入目的操作数中,无精度损失。
示例:输入:-1,输出:-1.0。
int8_t → int16_t
将源值以int16_t格式存入目的操作数中,无精度损失。
示例:输入:
int8_t → int32_t
将源值以int32_t格式存入目的操作数中,无精度损失。
示例:输入:
uint8_t → half
将源值以half格式存入目的操作数中,无精度损失。
示例:输入:1,输出:1.0。
uint8_t → uint16_t
将源值以uint16_t格式存入目的操作数中,无精度损失。
示例:输入:
uint8_t → uint32_t
将源值以uint32_t格式存入目的操作数中,无精度损失。
示例:输入:
fp4x2_e2m1_t → bfloat16_t
将源值以bfloat16_t格式存入目的操作数中,无精度损失。
示例:输入:2,输出:2。
fp4x2_e1m2_t → bfloat16_t
将源值以bfloat16_t格式存入目的操作数中,无精度损失。
示例:输入:2,输出:2。
hifloat8_t → float
将源值以float格式存入目的操作数中,无精度损失。
示例:输入:2,输出:2。
hifloat8_t → half
将源值以half格式存入目的操作数中,无精度损失。
示例:输入:2,输出:2。
fp8_e5m2_t → float
将源值以float格式存入目的操作数中,无精度损失。
示例:输入:2,输出:2。
fp8_e4m3fn_t → float
将源值以float格式存入目的操作数中,无精度损失。
示例:输入:2,输出:2。
int16_t → int4b_t
将源值以int4b_t格式存入目的操作数中。
示例:输入:
int16_t → uint8_t
将源值以uint8_t格式存入目的操作数中,高位截断,存在精度损失。负数输入会被视为异常。
示例:输入:
int16_t → half
将源值按照精度舍入模式取到half所能表示的数,以half格式存入目的操作数中。
示例:输入:
图2 int16_t转half

由于half只有10bit尾数,因此灰色部分要进行舍入:
- CAST_RINT模式输入得尾数
0000000000,, ,最终结果为: 。 - CAST_FLOOR模式输入得尾数
0000000000,, ,最终结果为: 。 - CAST_CEIL模式舍入得尾数
0000000001,, ,最终结果为: 。 - CAST_ROUND模式舍入得尾数
0000000001,, ,最终结果为: 。 - CAST_TRUNC模式舍入得尾数
0000000000,, ,最终结果为: 。
int16_t → uint32_t
将源值以uint32_t格式存入目的操作数中,无精度损失。负数输入会默认转换成0。
示例:输入:
int16_t → int32_t
将源值以int32_t格式存入目的操作数中,无精度损失。
示例:输入:
int16_t → float
将源值以float格式存入目的操作数中,无精度损失。
示例:输入:
uint16_t → uint8_t
将源值以uint8_t格式存入目的操作数中。
示例:输入:
uint16_t → uint32_t
将源值以uint32_t格式存入目的操作数中,无精度损失。
示例:输入:
half → int4b_t
将源值按照精度舍入模式取整,以int4b_t格式存入目的操作数中。
示例:输入:
- CAST_RINT模式输出:
。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
。 - CAST_ROUND模式输出:
。 - CAST_TRUNC模式输出:
。
half → int8_t
将源值按照精度舍入模式取整,以int8_t格式存入目的操作数中。
示例:输入:
- CAST_RINT模式输出:
(溢出处理)。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
(溢出处理)。 - CAST_ROUND模式输出:
(溢出处理)。 - CAST_TRUNC模式输出:
。
half → uint8_t
将源值按照精度舍入模式取整,以uint8_t格式存入目的操作数中。负数输入会被视为异常。
示例:输入:
- CAST_RINT模式输出:
。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
。 - CAST_ROUND模式输出:
。 - CAST_TRUNC模式输出:
。
half → hifloat8_t
将源值按照精度舍入模式取整,以hifloat8_t格式存入目的操作数中。
示例:输入:
- CAST_ROUND模式输出:
。 - CAST_HYBRID模式,参考half to hifloat8_t类型转换规则的输出。
half → int16_t
将源值按照精度舍入模式取整,以int16_t格式存入目的操作数中。
示例:输入:
- CAST_RINT模式输出:
。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
。 - CAST_ROUND模式输出:
。 - CAST_TRUNC模式输出:
。
half → bfloat16_t
将源值按照精度舍入模式取整,以bfloat16_t格式存入目的操作数中。
示例:输入:
- CAST_RINT模式输出:
。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
。 - CAST_ROUND模式输出:
。 - CAST_TRUNC模式输出:
。
half → int32_t
将源值按照精度舍入模式取整,以int32_t格式存入目的操作数中。
示例:输入:
。 - CAST_RINT模式输出:
。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
。 - CAST_ROUND模式输出:
。 - CAST_TRUNC模式输出:
。
- CAST_RINT模式输出:
half → float
将源值以float格式存入目的操作数中,无精度损失。
示例:输入:
bfloat16_t → fp4x2_e2m1_t
将源值按照精度舍入模式取整,以fp4x2_e2m1_t格式存入目的操作数中。
示例:输入:2.5。
- CAST_RINT模式输出:2。
- CAST_FLOOR模式输出:2。
- CAST_CEIL模式输出:3。
- CAST_ROUND模式输出:3。
- CAST_TRUNC模式输出:2。
bfloat16_t → fp4x2_e1m2_t
将源值按照精度舍入模式取整,以fp4x2_e1m2_t格式存入目的操作数中。
示例:输入:2.5。
- CAST_RINT模式输出:2。
- CAST_FLOOR模式输出:2。
- CAST_CEIL模式输出:3。
- CAST_ROUND模式输出:3。
- CAST_TRUNC模式输出:2。
bfloat16_t → half
将源值按照精度舍入模式取整,以half格式存入目的操作数中。
示例:输入:
- CAST_RINT模式输出:
。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
。 - CAST_ROUND模式输出:
。 - CAST_TRUNC模式输出:
。
bfloat16_t → int32_t
将源值按照精度舍入模式取整,以int32_t格式存入目的操作数中。
示例:输入:
- CAST_RINT模式输出:
。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
。 - CAST_ROUND模式输出:
。 - CAST_TRUNC模式输出:
。
bfloat16_t → float
将源值以float格式存入目的操作数中,无精度损失。
示例:输入:
int32_t → uint8_t
将源值以uint8_t格式存入目的操作数中,高位截断,存在精度损失。负数输入会被视为异常。
示例:输入:
int32_t → uint16_t
将源值以uint16_t格式存入目的操作数中,高位截断,存在精度损失。负数输入会被视为异常。
示例:输入:
int32_t → int16_t
将源值以int16_t格式存入目的操作数中。
示例:输入:
int32_t → half
当前数据类型组合仅支持配合SetDeqScale接口使用进行数据量化并完成精度转换,精度舍入模式不生效。
输出:
int32_t → float
将源值按照精度舍入模式取到float所能表示的数,以float格式存入目的操作数中。
示例:输入:
图3 int32_t转float

由于float只有23bit尾数,因此灰色部分要进行舍入:
- CAST_RINT模式舍入得尾数
00000000000000000000001,, ,最终结果为 。 - CAST_FLOOR模式舍入得尾数
00000000000000000000000,, ,最终结果为 。 - CAST_CEIL模式舍入得尾数
00000000000000000000001,, ,最终结果为 。 - CAST_ROUND模式舍入得尾数
00000000000000000000001,, ,最终结果为 。 - CAST_TRUNC模式舍入得尾数
00000000000000000000000,, ,最终结果为 。
int32_t → int64_t
将源值以int64_t格式存入目的操作数中,无精度损失。
示例:输入:
uint32_t → uint8_t
将源值以uint8_t格式存入目的操作数中。
示例:输入:
uint32_t → uint16_t
将源值以uint16_t格式存入目的操作数中。
示例:输入:
uint32_t → int16_t
将源值以int16_t格式存入目的操作数中。
示例:输入:
float → hifloat8_t
将源值按照精度舍入模式取整,以hifloat8_t格式存入目的操作数中。
示例:输入:
- CAST_ROUND模式输出:
。 - CAST_HYBRID模式,参考float to hifloat8_t类型转换规则的输出。
float → fp8_e4m3fn_t
将源值按照精度舍入模式取整,以fp8_e4m3fn_t格式存入目的操作数中。
示例:输入:
float → fp8_e5m2_t
将源值按照精度舍入模式取整,以fp8_e5m2_t格式存入目的操作数中。
示例:输入:
float → int16_t
将源值按照精度舍入模式取整,以int16_t格式存入目的操作数中。
示例:输入:
- CAST_RINT模式输出:
(溢出处理)。 - CAST_FLOOR模式输出:
(溢出处理)。 - CAST_CEIL模式输出:
(溢出处理)。 - CAST_ROUND模式输出:
(溢出处理)。 - CAST_TRUNC模式输出:
(溢出处理)。
float → half
将源值按照精度舍入模式取到half所能表示的数,以half格式存入目的操作数中。
示例:输入:
图4 float转half

half的指数位可以表示出
- CAST_RINT模式舍入得尾数
0000000000,, ,最终结果为 。 - CAST_FLOOR模式舍入得尾数
0000000000,, ,最终结果为 。 - CAST_CEIL模式舍入得尾数
0000000001,, ,最终结果为 。 - CAST_ROUND模式舍入得尾数
0000000001,, ,最终结果为 。 - CAST_TRUNC模式舍入得尾数
0000000000,, ,最终结果为 。 - CAST_ODD模式舍入得尾数
0000000001,, ,最终结果为 。
float → bfloat16_t
将源值按照精度舍入模式取到bfloat16_t所能表示的数,以bfloat16_t格式存入目的操作数中。
示例:输入:
图5 float转bfloat16_t

bfloat16_t的指数位位数和float相同,有
- CAST_RINT模式舍入得尾数
0000001,, ,最终结果为 。 - CAST_FLOOR模式舍入得尾数
0000000,, ,最终结果为 。 - CAST_CEIL模式舍入得尾数
0000001,, ,最终结果为 。 - CAST_ROUND模式舍入得尾数
0000001,, ,最终结果为 。 - CAST_TRUNC模式舍入得尾数
0000000,, ,最终结果为 。
float → int32_t
将源值按照精度舍入模式取整,以int32_t格式存入目的操作数中。
示例:输入:
- CAST_RINT模式输出:
。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
。 - CAST_ROUND模式输出:
。 - CAST_TRUNC模式输出:
。
float → float
将源值按照精度舍入模式取整,仍以float格式存入目的操作数中。
示例:输入:
- CAST_RINT模式输出:
。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
。 - CAST_ROUND模式输出:
。 - CAST_TRUNC模式输出:
。
float → int64_t
将源值按照精度舍入模式取整,以int64_t格式存入目的操作数中。
示例:输入:
- CAST_RINT模式输出:
。 - CAST_FLOOR模式输出:
。 - CAST_CEIL模式输出:
。 - CAST_ROUND模式输出:
。 - CAST_TRUNC模式输出:
。
complex32 → complex64
complex64实部和虚部都是float类型,complex32实部和虚部都是half类型,参考从half到float的精度转换规则。
int64_t → int32_t
将源值以int32_t格式存入目的操作数中。
示例:输入:
int64_t → float
将源值按照精度舍入模式取到float所能表示的数,以float格式存入目的操作数中。
示例:输入:
图6 int64_t转float

由于float只有23bit尾数,因此灰色部分要进行舍入:
- CAST_RINT模式舍入得尾数
00000000000000000000010,, ,最终结果为 。 - CAST_FLOOR模式舍入得尾数
00000000000000000000001,, ,最终结果为 。 - CAST_CEIL模式舍入得尾数
00000000000000000000010,, ,最终结果为 。 - CAST_ROUND模式舍入得尾数
00000000000000000000010,, ,最终结果为 。 - CAST_TRUNC模式舍入得尾数
00000000000000000000001,, ,最终结果为 。
int64_t → double
将源值按照精度舍入模式取到double所能表示的数,以double格式存入目的操作数中。
示例:输入:
图7 int64_t转double示意图

由于double只有52bit尾数,因此灰色部分要进行舍入:
- CAST_RINT模式舍入得尾数
...010,, ,最终表示的结果为 。 - CAST_FLOOR模式舍入得尾数
...001,, ,最终表示的结果为 。 - CAST_CEIL模式舍入得尾数
...010,, ,最终表示的结果为 。 - CAST_ROUND模式舍入得尾数
...010,, ,最终表示的结果为 。 - CAST_TRUNC模式舍入得尾数
...001,, ,最终表示的结果为 。
double → float
将源值按照精度舍入模式取到float所能表示的数,以float格式存入目的操作数中。
示例:输入:
图8 double转float示意图

由于float只有8bit指数,指数部分需要转换,只有23bit尾数,因此灰色部分要进行舍入:
- CAST_RINT模式舍入得尾数00000000000000000000010,
, ,最终表示的结果为 。 - CAST_FLOOR模式舍入得尾数00000000000000000000001,
, ,最终表示的结果为 。 - CAST_CEIL模式舍入得尾数00000000000000000000010,
, ,最终表示的结果为 。 - CAST_ROUND模式舍入得尾数00000000000000000000010,
, ,最终表示的结果为 。 - CAST_TRUNC模式舍入得尾数00000000000000000000001,
, ,最终表示的结果为 。
double → bfloat16_t
将源值按照精度舍入模式取到bfloat16_t所能表示的数,以bfloat16_t格式存入目的操作数中。
示例:输入:
图9 double转bfloat16_t示意图

由于bfloat16_t只有8bit指数,指数部分需要转换,只有7bit尾数,因此灰色部分要进行舍入:
- CAST_RINT模式舍入得尾数0000010,
, ,最终表示的结果为 。 - CAST_FLOOR模式舍入得尾数0000001,
, ,最终表示的结果为 。 - CAST_CEIL模式舍入得尾数0000010,
, ,最终表示的结果为 。 - CAST_ROUND模式舍入得尾数0000010,
, ,最终表示的结果为 。 - CAST_TRUNC模式舍入得尾数0000001,
, ,最终表示的结果为 。
double → int32_t
将源值按照精度舍入模式取整,以int32_t格式存入目的操作数中。
示例:输入:-1.5,CAST_TRUNC模式输出:-1。
double → int64_t
将源值按照精度舍入模式取整,以int64_t格式存入目的操作数中。
示例:输入:-1.5,CAST_TRUNC模式输出:-1。
complex64 → complex64
complex64实部和虚部都是float类型,参考float与float之间的精度转换规则。
complex64 → complex32
complex64实部和虚部都是float类型,complex32实部和虚部都是half类型,参考从float到half的精度转换规则。