python float和Java float引发的问题

探讨Python与Java中浮点数的实现差异,特别是针对xgboost模型预测时的数据类型不一致问题,分析了Python float与Java float的底层结构,并通过示例展示了不同精度下数值的表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

离线特征是python加工出来的,在python中默认也是float类型,java中xgboost相关的api也都是float类型,为啥进行特征比对的时候结果就不一致呢?

这就涉及到底层数据结构的实现了,也就是本篇的由来,下面我们一探究竟。

在进行xgboost模型线上特征加工的时候,数据是采用Java float存储,为啥采用float呢?

因为如下的Booster api
​
public float[][] predict(DMatrix data, boolean outputMargin, int treeLimit) throws XGBoostError

​

Java预测时候,入参为DMatrix,数据是用的float类型

​# https://xgboost.readthedocs.io/en/release_1.5.0/jvm/javadocs/index.html
public DMatrix(float[] data,
               int nrow,
               int ncol,
               float missing)
        throws XGBoostError
create DMatrix from dense matrix

Parameters:

data - data values

nrow - number of rows

ncol - number of columns

missing - the specified value to represent the missing value

​

在Java中 float占用4个字节,包括:

  • 1bit(符号位):0表示正数,1表示负数;
  • 8bits(指数位):float的偏移量为2^8 - 1,double的偏移量为2^11 - 1;
  • 23bits(尾数位):实际尾数部分中的小数点后的数值,规约浮点数使用标准的二进制科学计数法表示,其尾数范围在 [1,2),非规约浮点数的尾数部分范围在(0,1)

 

python中float类型是如何实现的?

python中的数值类型

共有三种不同的数值类型:整数浮点数复数。此外,布尔值是整数的一个子类型。

整数具有无限精度。

浮点数通常在 C 中使用double实现;有关运行程序的机器的浮点数精度和内部表示的信息可在sys.float_info. (这个就是Java float和python float数据存在差异的原因)

所以float是8个字节是真正的数字,但是float对象是24字节的。

复数具有实部和虚部,每个都是浮点数。要从复数z中提取这些部分,请使用z.realz.imag。(标准库包括额外的数字类型fractions.Fraction,用于有理数,和decimal.Decimal,用于具有用户可定义精度的浮点数。)

参见:Built-in Types — Python 3.11.0 documentation

案例重现

python具体示例:

>>> float(0.63693581908)

0.63693581908

>>> np.float16(0.63693581908)

0.6367

>>> np.float32(0.63693581908)

0.63693583

>>> np.float64(0.63693581908)

0.63693581908

Java具体示例

double a = -636935.81908;
float b = (float) -636935.81908;
float c = (float) -0.63693581908;
float d = (float) 0.63693581908;

System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);

-636935.81908
-636935.8
-0.63693583
0.63693583

结论:

1、python中的float是和Java中的double是精度一样的

2、numpy中的float32是和Java中的float是等价的

所以在进行特征&模型结果比对的时候,最好按照这种结论中的形式进行数据精度对齐,保持结果一致。

### 如何在 Python 中将 `float` 类型转换为 `float64` 类型 在 Python 的 NumPy 库中,可以轻松实现从标准的 `float` 到更具体的 `float64` 数据类型的转换。NumPy 提供了一种机制用于显式指定数据类型,在这种情况下可以通过强制类型转换完成目标。 以下是具体的方法: #### 使用 NumPy 进行类型转换 通过 NumPy 的 `astype()` 函数,能够方便地将数组中的元素转换为目标数据类型。对于单个值或者整个数组都可以应用此方法[^1]。 ```python import numpy as np # 定义一个普通的浮点数 value = 3.14 # 转换为 float64 类型 converted_value = np.float64(value) print(f"原始值: {type(value)}, 转换后值: {type(converted_value)}") ``` 上述代码展示了如何利用 NumPy 将常规的 `float` 值转化为精确到 64 位精度的浮点数值。需要注意的是,尽管 Python 默认使用的已经是双精度浮点数 (即相当于 C++ 或 Java 中的 double),但在某些特定场景下可能仍需明确声明其为 `float64`[^2]。 #### 处理潜在异常情况 当涉及大量数据操作时(例如 CSV 文件读取),可能会遇到诸如缺失值 (`NaN`) 或者非法字符串等问题导致转换失败。针对这种情况可采取如下措施: - **检测并过滤掉无效输入**: 对于含有非数字字符的数据项提前剔除或修正后再执行转型逻辑。 ```python try: valid_number = float('invalid_string') except ValueError: print("无法解析该字符串为有效数字.") ``` - **运用自定义辅助函数规避风险**: 参考先前提到的例子构建健壮性更高的解决方案[^3]。 最后值得注意的一点在于,如果源数据本身已经是以某种形式存在的 NumPy 数组,则可以直接调用 `.astype(np.float64)` 来批量更改所有成员变量至所需类别而无需逐一遍历处理每一个单独单元格的内容[^4].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mtj66

看心情

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值