应统一用字符串或整型缩放存储小数,避免php与java浮点类型差异导致精度丢失、字节序错位等问题;json中须转字符串再解析,二进制协议需显式指定字节序和格式。
PHP保存小数时Java解析失败,大概率是浮点类型不一致
PHP默认用float(IEEE 754双精度)存小数,Java端若用float或BigDecimal按不同规则解析,就会出现精度偏差、字节错位甚至NumberFormatException。这不是传输问题,而是两端对“小数”没约定好物理表示形式。
常见现象包括:
- PHP写
12.34,Java读成12.339999999999999 - JSON里传
"12.34",Java用Float.parseFloat()后值不准 - 二进制直传(如TCP/UDP)时,PHP用
pack('d', 12.34),Java用ByteBuffer.order(ByteOrder.LITTLE_ENDIAN).getDouble()却读出乱值——字节序没对齐
必须统一为定点数,推荐字符串或整型缩放存储
跨语言场景下,float/double天生不可靠。最稳的方式是放弃“小数”这个概念,改用整数表达“最小单位”,再由业务层解释小数点位置。
例如金额统一到“分”:
立即学习“PHP免费学习笔记(深入)”;
- PHP存:
$cents = (int)round(12.34 * 100); // 得 1234,传1234(int)或"1234"(string) - Java收:
BigDecimal.valueOf(cents).divide(BigDecimal.ONE_HUNDRED)
如果必须传小数字符串(如JSON API),PHP用number_format($val, 2, '.', '')强制两位,避免12.340000000000001这类输出;Java端用new BigDecimal(str)构造,绝不用Double.parseDouble()。
pack/unpack与Java二进制互通需显式指定字节序和格式
若走二进制协议(如自定义报文、Redis raw value),PHP的pack()默认按本机字节序,JavaByteBuffer默认大端(BIG_ENDIAN),x86机器PHP通常是小端,直接对接必错。