Kotlin中Long与字节数组互转异常:Double还原值偏差排查
问题:Double转字节数组后还原值不一致
近期尝试将包含若干基本类型变量的类对象转换为字节数组时,遇到一个问题:将Double保存为8字节格式后,还原得到的值与原数值接近但不完全一致。
测试过表达式 val value = Double.fromBits(1.2.toBits()),结果完全正确,因此推测问题出在自己实现的Long与字节数组互转逻辑中,但无法定位具体bug。
以下是相关实现代码:
写入字节数组(Long转ByteArray)
fun from(value : Long) : ByteArray{ val byteArray = ByteArray(Long.SIZE_BYTES) var index = 0 var shift = 8 * Long.SIZE_BYTES while(index < Long.SIZE_BYTES){ shift -= 8 byteArray[index] = value.shr(shift).and(0xFFL).toByte() index++ } return byteArray }
从字节数组读取(ByteArray转Long)
fun read(byteArray: ByteArray) : Long{ var value = 0L var index = 0 while(index < Long.SIZE_BYTES){ value = value.shl(8) + byteArray[index].toLong() index++ } return value }
问题定位与修复
问题出在read方法中的byteArray[index].toLong():Kotlin的Byte是有符号类型(取值范围-128~127),当字节的原始值大于127时,toLong()会进行符号扩展,将其转换为负数的Long值,导致最终计算出的Long数值错误,进而还原Double时出现精度偏差。
修复后的read方法只需对字节转Long的结果做无符号掩码处理:
fun read(byteArray: ByteArray) : Long{ var value = 0L var index = 0 while(index < Long.SIZE_BYTES){ value = value.shl(8) + byteArray[index].toLong().and(0xFFL) index++ } return value }
修复后,Long与字节数组的互转可以完全准确对应,Double还原后的值也会和原数值完全一致。
内容的提问来源于stack exchange,提问作者Giebut
相关产品推荐
相关产品推荐

