📅  最后修改于: 2023-12-03 15:37:45.851000             🧑  作者: Mango
在很多嵌入式系统和通讯协议中,经常使用定点数表示浮点数,比如 16.16 位定点数和 32.32 位定点数。64.64 位定点数可以表示更高的精度,但在计算机中无法直接转换为浮点数,需要特别的算法。
本文介绍使用 Javascript 实现在线转换有符号的 64.64 位定点数的算法,并提供代码示例。
定点数是以固定小数点位置表示的数字,它的值是整数部分和小数部分的和,具体表示方法如下:
给定一个整数 n,将该整数左移位长为 p,即可得到定点数 n × 2^p。
例如,16.16 位定点数表示方法是将数值乘以 2^16,然后将结果表示成二进制数。例如,十进制数 1.234 的 16.16 位定点数表示为二进制数 00000001000011100100001100000000。
64.64 位定点数的表示方法类似,即将数值乘以 2^64。然后将结果表示成二进制数。
对于 64.64 位定点数,可以将其分为高 64 位和低 64 位,其中高 64 位表示整数部分,低 64 位表示小数部分。
设要转换的定点数为 a,高 64 位为 a_high,低 64 位为 a_low。
首先,应该将 a 转为二进制数,然后分别取出高 64 位和低 64 位。由于 Javascript 的数值类型不能表示超过 2^53 的整数,因此可以使用 BigInteger 库。
代码示例如下:
// 引入 BigInteger.js 库
const { BigInteger } = require('jsbn');
// a 为要转换的定点数
const a = "1234567890123.4567890123456";
// 将 a 转为 BigInteger 类型
const a_bigint = new BigInteger(a.replace(".", ""), 10);
// 获取 a 的二进制表示,并分别取出高 64 位和低 64 位
const binary_str = a_bigint.toString(2);
const binary_len = binary_str.length;
const a_high = binary_str.slice(0, binary_len - 64);
const a_low = binary_str.slice(binary_len - 64);
转换完成后,就可以将 a_high 和 a_low 转回十进制数,进而得到原始的定点数。具体代码示例如下:
// 将高 64 位和低 64 位转回二进制数,并组合成一个 128 位的二进制数
const binary_str = a_high + a_low;
const a_binary = new BigInteger(binary_str, 2);
// 将二进制数除以 2^64,得到原始的定点数
const a_value = a_binary.divide(new BigInteger("18446744073709551616")).toString();
// 将整数部分和小数部分分离出来
const a_int = a_value.slice(0, a_value.length - 16);
const a_dec = a_value.slice(a_value.length - 16).padStart(16, "0");
// 将整数部分和小数部分组合成一个带小数点的字符串
const a_str = a_int + "." + a_dec;
// 引入 BigInteger.js 库
const { BigInteger } = require('jsbn');
function convert_fixed_point_number(a) {
// 将 a 转为 BigInteger 类型
const a_bigint = new BigInteger(a.replace(".", ""), 10);
// 获取 a 的二进制表示,并分别取出高 64 位和低 64 位
const binary_str = a_bigint.toString(2);
const binary_len = binary_str.length;
const a_high = binary_str.slice(0, binary_len - 64);
const a_low = binary_str.slice(binary_len - 64);
// 将高 64 位和低 64 位转回二进制数,并组合成一个 128 位的二进制数
const binary_str2 = a_high + a_low;
const a_binary = new BigInteger(binary_str2, 2);
// 将二进制数除以 2^64,得到原始的定点数
const a_value = a_binary.divide(new BigInteger("18446744073709551616")).toString();
// 将整数部分和小数部分分离出来
const a_int = a_value.slice(0, a_value.length - 16);
const a_dec = a_value.slice(a_value.length - 16).padStart(16, "0");
// 将整数部分和小数部分组合成一个带小数点的字符串
const a_str = a_int + "." + a_dec;
return a_str;
}
在线转换有符号的 64.64 位定点数可以使用 Javascript 中的 BigInteger.js 库实现。通过将定点数转为二进制数,并分别取出高 64 位和低 64 位,然后将其转回十进制数即可实现转换。
完整代码示例如上。