精度转换【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit二进制精度舍入规则在了解不同类型之间的精度转换规则之前需先了解二进制的精度舍入规则。如下图所示一个二进制数的尾部若干位可能因目标精度不足而被丢弃这部分称为待舍入部分剩余保留的部分称为非舍入部分。根据待舍入部分的值以及所选的精度舍入模式决定非舍入部分的末位是否需要1进位。图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格式存入目的操作数中无精度损失。示例输入$2^7 - 1$输出$2^7 - 1$。int8_t → int32_t将源值以int32_t格式存入目的操作数中无精度损失。示例输入$2^7 - 1$输出$2^7 - 1$。uint8_t → half将源值以half格式存入目的操作数中无精度损失。示例输入1输出1.0。uint8_t → uint16_t将源值以uint16_t格式存入目的操作数中无精度损失。示例输入$2^8 - 1$输出$2^8 - 1$。uint8_t → uint32_t将源值以uint32_t格式存入目的操作数中无精度损失。示例输入$2^8 - 1$输出$2^8 - 1$。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格式存入目的操作数中。示例输入$2^{15} - 1$输出$2^3 - 1$。int16_t → uint8_t将源值以uint8_t格式存入目的操作数中高位截断存在精度损失。负数输入会被视为异常。示例输入$2^{15} - 1$输出$2^8 - 1$。int16_t → half将源值按照精度舍入模式取到half所能表示的数以half格式存入目的操作数中。示例输入$2^{12} 2$写成half的表示形式$2^{12} \times (1 2^{-11})$要求$E_v 12 15 27$$M_v 2^{-11}$。图2int16_t转half由于half只有10bit尾数因此灰色部分要进行舍入CAST_RINT模式输入得尾数0000000000$E_v 27$$M_v 0$最终结果为$2^{12}$。CAST_FLOOR模式输入得尾数0000000000$E_v 27$$M_v 0$最终结果为$2^{12}$。CAST_CEIL模式舍入得尾数0000000001$E_v 27$$M_v 2^{-10}$最终结果为$2^{12} 4$。CAST_ROUND模式舍入得尾数0000000001$E_v 27$$M_v 2^{-10}$最终结果为$2^{12} 4$。CAST_TRUNC模式舍入得尾数0000000000$E_v 27$$M_v 0$最终结果为$2^{12}$。int16_t → uint32_t将源值以uint32_t格式存入目的操作数中无精度损失。负数输入会默认转换成0。示例输入$2^{15} - 1$输出$2^{15} - 1$。int16_t → int32_t将源值以int32_t格式存入目的操作数中无精度损失。示例输入$2^{15} - 1$输出$2^{15} - 1$。int16_t → float将源值以float格式存入目的操作数中无精度损失。示例输入$2^{15} - 1$输出$2^{15} - 1$。uint16_t → uint8_t将源值以uint8_t格式存入目的操作数中。示例输入$2^{16} - 1$输出$2^8 - 1$。uint16_t → uint32_t将源值以uint32_t格式存入目的操作数中无精度损失。示例输入$2^{16} - 1$输出$2^{16} - 1$。half → int4b_t将源值按照精度舍入模式取整以int4b_t格式存入目的操作数中。示例输入$1.5$小数部分需要舍入。CAST_RINT模式输出$2$。CAST_FLOOR模式输出$1$。CAST_CEIL模式输出$2$。CAST_ROUND模式输出$2$。CAST_TRUNC模式输出$1$。half → int8_t将源值按照精度舍入模式取整以int8_t格式存入目的操作数中。示例输入$2^{7} - 0.5$。CAST_RINT模式输出$2^{7} - 1$溢出处理。CAST_FLOOR模式输出$2^{7} - 1$。CAST_CEIL模式输出$2^{7} - 1$溢出处理。CAST_ROUND模式输出$2^{7} - 1$溢出处理。CAST_TRUNC模式输出$2^{7} - 1$。half → uint8_t将源值按照精度舍入模式取整以uint8_t格式存入目的操作数中。负数输入会被视为异常。示例输入$1.75$。CAST_RINT模式输出$2$。CAST_FLOOR模式输出$1$。CAST_CEIL模式输出$2$。CAST_ROUND模式输出$2$。CAST_TRUNC模式输出$1$。half → hifloat8_t将源值按照精度舍入模式取整以hifloat8_t格式存入目的操作数中。示例输入$1.75$。CAST_ROUND模式输出$2$。CAST_HYBRID模式参考half to hifloat8_t类型转换规则的输出。half → int16_t将源值按照精度舍入模式取整以int16_t格式存入目的操作数中。示例输入$2^{7} - 0.5$。CAST_RINT模式输出$2^{7}$。CAST_FLOOR模式输出$2^{7} - 1$。CAST_CEIL模式输出$2^{7}$。CAST_ROUND模式输出$2^{7}$。CAST_TRUNC模式输出$2^{7} - 1$。half → bfloat16_t将源值按照精度舍入模式取整以bfloat16_t格式存入目的操作数中。示例输入$1.75$。CAST_RINT模式输出$2$。CAST_FLOOR模式输出$1$。CAST_CEIL模式输出$2$。CAST_ROUND模式输出$2$。CAST_TRUNC模式输出$1$。half → int32_t将源值按照精度舍入模式取整以int32_t格式存入目的操作数中。示例输入$-1.5$。CAST_RINT模式输出$-2$。CAST_FLOOR模式输出$-2$。CAST_CEIL模式输出$-1$。CAST_ROUND模式输出$-2$。CAST_TRUNC模式输出$-1$。half → float将源值以float格式存入目的操作数中无精度损失。示例输入$1.5 - 2^-10$输出$1.5 - 2^-10$。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格式存入目的操作数中。示例输入$2.90573e-06$。CAST_RINT模式输出$2.9e-06$。CAST_FLOOR模式输出$2.861e-06$。CAST_CEIL模式输出$2.9e-06$。CAST_ROUND模式输出$2.9e-06$。CAST_TRUNC模式输出$2.861e-06$。bfloat16_t → int32_t将源值按照精度舍入模式取整以int32_t格式存入目的操作数中。示例输入$2^{6} 0.5$。CAST_RINT模式输出$2^{6}$。CAST_FLOOR模式输出$2^{6}$。CAST_CEIL模式输出$2^{6} 1$。CAST_ROUND模式输出$2^{6} 1$。CAST_TRUNC模式输出$2^{6}$。bfloat16_t → float将源值以float格式存入目的操作数中无精度损失。示例输入$1.5 - 2^{-6}$输出$1.5 - 2^{-6}$。int32_t → uint8_t将源值以uint8_t格式存入目的操作数中高位截断存在精度损失。负数输入会被视为异常。示例输入$2^{31} - 1$输出$2^8 - 1$。int32_t → uint16_t将源值以uint16_t格式存入目的操作数中高位截断存在精度损失。负数输入会被视为异常。示例输入$2^{31} - 1$输出$2^{16} - 1$。int32_t → int16_t将源值以int16_t格式存入目的操作数中。示例输入$2^{31} - 1$输出$2^{15} - 1$。int32_t → half当前数据类型组合仅支持配合SetDeqScale接口使用进行数据量化并完成精度转换精度舍入模式不生效。输出$src / 2^{17} \times scale \times 2^{17}$。int32_t → float将源值按照精度舍入模式取到float所能表示的数以float格式存入目的操作数中。示例输入$2^{25} 3$写成float的表示形式$2^{25} \times (1 2^{-24} 2^{-25})$要求$E_v 25 127 152$$M_v 2^{-24} 2^{-25}$。图3int32_t转float由于float只有23bit尾数因此灰色部分要进行舍入CAST_RINT模式舍入得尾数00000000000000000000001$E_v 152$$M_v 2^{-23}$最终结果为$2^{25} 4$。CAST_FLOOR模式舍入得尾数00000000000000000000000$E_v 152$$M_v 0$最终结果为$2^{25}$。CAST_CEIL模式舍入得尾数00000000000000000000001$E_v 152$$M_v 2^{-23}$最终结果为$2^{25} 4$。CAST_ROUND模式舍入得尾数00000000000000000000001$E_v 152$$M_v 2^{-23}$最终结果为$2^{25} 4$。CAST_TRUNC模式舍入得尾数00000000000000000000000$E_v 152$$M_v 0$最终结果为$2^{25}$。int32_t → int64_t将源值以int64_t格式存入目的操作数中无精度损失。示例输入$2^{31} - 1$输出$2^{31} - 1$。uint32_t → uint8_t将源值以uint8_t格式存入目的操作数中。示例输入$2^{32} - 1$输出$2^8 - 1$。uint32_t → uint16_t将源值以uint16_t格式存入目的操作数中。示例输入$2^{32} - 1$输出$2^{16} - 1$。uint32_t → int16_t将源值以int16_t格式存入目的操作数中。示例输入$2^{32} - 1$输出$2^{15} - 1$。float → hifloat8_t将源值按照精度舍入模式取整以hifloat8_t格式存入目的操作数中。示例输入$1.75$。CAST_ROUND模式输出$2$。CAST_HYBRID模式参考float to hifloat8_t类型转换规则的输出。float → fp8_e4m3fn_t将源值按照精度舍入模式取整以fp8_e4m3fn_t格式存入目的操作数中。示例输入$2.5$CAST_RINT模式输出$2$。float → fp8_e5m2_t将源值按照精度舍入模式取整以fp8_e5m2_t格式存入目的操作数中。示例输入$2.5$CAST_RINT模式输出$2$。float → int16_t将源值按照精度舍入模式取整以int16_t格式存入目的操作数中。示例输入$2^{22} 0.5$。CAST_RINT模式输出$2^{15} - 1$溢出处理。CAST_FLOOR模式输出$2^{15} - 1$溢出处理。CAST_CEIL模式输出$2^{15} - 1$溢出处理。CAST_ROUND模式输出$2^{15} - 1$溢出处理。CAST_TRUNC模式输出$2^{15} - 1$溢出处理。float → half将源值按照精度舍入模式取到half所能表示的数以half格式存入目的操作数中。示例输入$0.5 2^{-12}$写成float的表示形式$2^{-1} \times (1 2^{-11})$因此$E_v -1 127 126$$M_v 2^{-11}$。图4float转halfhalf的指数位可以表示出$2^{-1}$$E_v -1 15 14$但half只有10bit尾数因此灰色部分要进行舍入CAST_RINT模式舍入得尾数0000000000$E_v 14$$M_v 0$最终结果为$0.5$。CAST_FLOOR模式舍入得尾数0000000000$E_v 14$$M_v 0$最终结果为$0.5$。CAST_CEIL模式舍入得尾数0000000001$E_v 14$$M_v 2^{-10}$最终结果为$0.5 2^{-11}$。CAST_ROUND模式舍入得尾数0000000001$E_v 14$$M_v 2^{-10}$最终结果为$0.5 2^{-11}$。CAST_TRUNC模式舍入得尾数0000000000$E_v 14$$M_v 0$最终结果为$0.5$。CAST_ODD模式舍入得尾数0000000001$E_v 14$$M_v 2^{-10}$最终结果为$0.5 2^{-11}$。float → bfloat16_t将源值按照精度舍入模式取到bfloat16_t所能表示的数以bfloat16_t格式存入目的操作数中。示例输入$0.5 2^{-9} 2^{-11}$写成float的表示形式$2^{-1} \times (1 2^{-8} 2^{-10})$因此$E_v -1 127 126$$M_v 2^{-8} 2^{-10}$。图5float转bfloat16_tbfloat16_t的指数位位数和float相同有$E_v 126$但bfloat16_t只有7bit尾数因此灰色部分要进行舍入CAST_RINT模式舍入得尾数0000001$E_v 126$$M_v 2^{-7}$最终结果为$0.5 2^{-8}$。CAST_FLOOR模式舍入得尾数0000000$E_v 126$$M_v 0$最终结果为$0.5$。CAST_CEIL模式舍入得尾数0000001$E_v 126$$M_v 2^{-7}$最终结果为$0.5 2^{-8}$。CAST_ROUND模式舍入得尾数0000001$E_v 126$$M_v 2^{-7}$最终结果为$0.5 2^{-8}$。CAST_TRUNC模式舍入得尾数0000000$E_v 126$$M_v 0$最终结果为$0.5$。float → int32_t将源值按照精度舍入模式取整以int32_t格式存入目的操作数中。示例输入$2^{22} 0.5$。CAST_RINT模式输出$2^{22}$。CAST_FLOOR模式输出$2^{22}$。CAST_CEIL模式输出$2^{22} 1$。CAST_ROUND模式输出$2^{22} 1$。CAST_TRUNC模式输出$2^{22}$。float → float将源值按照精度舍入模式取整仍以float格式存入目的操作数中。示例输入$0.5$。CAST_RINT模式输出$0.0$。CAST_FLOOR模式输出$0.0$。CAST_CEIL模式输出$1.0$。CAST_ROUND模式输出$1.0$。CAST_TRUNC模式输出$0.0$。float → int64_t将源值按照精度舍入模式取整以int64_t格式存入目的操作数中。示例输入$2^{22} 0.5$。CAST_RINT模式输出$2^{22}$。CAST_FLOOR模式输出$2^{22}$。CAST_CEIL模式输出$2^{22} 1$。CAST_ROUND模式输出$2^{22} 1$。CAST_TRUNC模式输出$2^{22}$。complex32 → complex64complex64实部和虚部都是float类型complex32实部和虚部都是half类型参考从half到float的精度转换规则。int64_t → int32_t将源值以int32_t格式存入目的操作数中。示例输入$2^{31}$输出$2^{31} - 1$。int64_t → float将源值按照精度舍入模式取到float所能表示的数以float格式存入目的操作数中。示例输入$2^{35} 2^{12} 2^{11}$写成float的表示形式$2^{35} \times (1 2^{-23} 2^{-24})$要求$E_v 35 127 162$$M_v 2^{-23} 2^{-24}$。图6int64_t转float由于float只有23bit尾数因此灰色部分要进行舍入CAST_RINT模式舍入得尾数00000000000000000000010$E_v 162$$M_v 2^{-22}$最终结果为$2^{35} 2^{13}$。CAST_FLOOR模式舍入得尾数00000000000000000000001$E_v 162$$M_v 2^{-23}$最终结果为$2^{35} 2^{12}$。CAST_CEIL模式舍入得尾数00000000000000000000010$E_v 162$$M_v 2^{-22}$最终结果为$2^{35} 2^{13}$。CAST_ROUND模式舍入得尾数00000000000000000000010$E_v 162$$M_v 2^{-22}$最终结果为$2^{35} 2^{13}$。CAST_TRUNC模式舍入得尾数00000000000000000000001$E_v 162$$M_v 2^{-23}$最终结果为$2^{35} 2^{12}$。int64_t → double将源值按照精度舍入模式取到double所能表示的数以double格式存入目的操作数中。示例输入$2^{61} 2^9 2^8$写成double的表示形式$2^{61} \times (1 2^{-52} 2^{-53})$要求$E_v 61 1023 1084$$M_v 2^{-52} 2^{-53}$。图7int64_t转double示意图由于double只有52bit尾数因此灰色部分要进行舍入CAST_RINT模式舍入得尾数...010$E_v 1084$$M_v 2^{-51}$最终表示的结果为$2^{61} 2^{10}$。CAST_FLOOR模式舍入得尾数...001$E_v 1084$$M_v 2^{-52}$最终表示的结果为$2^{61} 2^9$。CAST_CEIL模式舍入得尾数...010$E_v 1084$$M_v 2^{-51}$最终表示的结果为$2^{61} 2^{10}$。CAST_ROUND模式舍入得尾数...010$E_v 1084$$M_v 2^{-51}$最终表示的结果为$2^{61} 2^{10}$。CAST_TRUNC模式舍入得尾数...001$E_v 1084$$M_v 2^{-52}$最终表示的结果为$2^{61} 2^9$。double → float将源值按照精度舍入模式取到float所能表示的数以float格式存入目的操作数中。示例输入$2^{35} 2^{12} 2^{11}$写成float的表示形式$2^{35} \times (1 2^{-23} 2^{-24})$要求$E_v 1058 - 1023 127 162$$M_v 2^{-23} 2^{-24}$。图8double转float示意图由于float只有8bit指数指数部分需要转换只有23bit尾数因此灰色部分要进行舍入CAST_RINT模式舍入得尾数00000000000000000000010$E_v 162$$M_v 2^{-22}$最终表示的结果为$2^{35} 2^{13}$。CAST_FLOOR模式舍入得尾数00000000000000000000001$E_v 162$$M_v 2^{-23}$最终表示的结果为$2^{35} 2^{12}$。CAST_CEIL模式舍入得尾数00000000000000000000010$E_v 162$$M_v 2^{-22}$最终表示的结果为$2^{35} 2^{13}$。CAST_ROUND模式舍入得尾数00000000000000000000010$E_v 162$$M_v 2^{-22}$最终表示的结果为$2^{35} 2^{13}$。CAST_TRUNC模式舍入得尾数00000000000000000000001$E_v 162$$M_v 2^{-23}$最终表示的结果为$2^{35} 2^{12}$。double → bfloat16_t将源值按照精度舍入模式取到bfloat16_t所能表示的数以bfloat16_t格式存入目的操作数中。示例输入$2^{35} 2^{28} 2^{27}$写成bfloat16_t的表示形式$2^{35} \times (1 2^{-7} 2^{-8})$要求$E_v 1058 - 1023 127 162$$M_v 2^{-7} 2^{-8}$。图9double转bfloat16_t示意图由于bfloat16_t只有8bit指数指数部分需要转换只有7bit尾数因此灰色部分要进行舍入CAST_RINT模式舍入得尾数0000010$E_v 162$$M_v 2^{-6}$最终表示的结果为$2^{35} 2^{29}$。CAST_FLOOR模式舍入得尾数0000001$E_v 162$$M_v 2^{-7}$最终表示的结果为$2^{35} 2^{28}$。CAST_CEIL模式舍入得尾数0000010$E_v 162$$M_v 2^{-6}$最终表示的结果为$2^{35} 2^{29}$。CAST_ROUND模式舍入得尾数0000010$E_v 162$$M_v 2^{-6}$最终表示的结果为$2^{35} 2^{29}$。CAST_TRUNC模式舍入得尾数0000001$E_v 162$$M_v 2^{-7}$最终表示的结果为$2^{35} 2^{28}$。double → int32_t将源值按照精度舍入模式取整以int32_t格式存入目的操作数中。示例输入-1.5CAST_TRUNC模式输出-1。double → int64_t将源值按照精度舍入模式取整以int64_t格式存入目的操作数中。示例输入-1.5CAST_TRUNC模式输出-1。complex64 → complex64complex64实部和虚部都是float类型参考float与float之间的精度转换规则。complex64 → complex32complex64实部和虚部都是float类型complex32实部和虚部都是half类型参考从float到half的精度转换规则。【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考