float double的精度损失

转:http://blog.youkuaiyun.com/fanfanjin/article/details/6908333

说的比较全面,但里面float四舍五入使用BigDecimal的方式有误,应为以下:

 

float d = 18896.45f;

BigDecimal b = new BigDecimal(Float.toString(d));
System.out.println(b.setScale(1, BigDecimal.ROUND_HALF_UP).floatValue());

 

红色代码不能使用强制转换(double) d,一样会有精度损失。

### 解决QString转换为double精度损失的问题 在Qt中,`QString::toDouble()` 方法用于将字符串转换为双精度浮点数。然而,在某些情况下,可能会遇到精度损失的问题。以下是几种解决方案,确保在转换过程中保留高精度。 #### 1. 使用 `QLocale` 进行精确转换 `QLocale` 提供了一种方法来处理不同区域设置下的数字格式化和解析问题。通过使用 `QLocale::toDouble()`,可以避免因小数点或千分位符号引起的解析错误。例如: ```cpp QLocale locale(QLocale::English, QLocale::UnitedStates); QString str = "123456789.123456789"; bool ok; double num = locale.toDouble(str, &ok); if (ok) { qDebug() << "Converted number:" << num; } else { qDebug() << "Conversion failed"; } ``` 此方法确保了即使在不同的区域设置下,也能正确解析字符串为双精度浮点数[^2]。 #### 2. 设置更高的精度 在转换前,可以通过调整显示的精度来减少潜在的精度损失。例如,使用 `QString::number()` 设置更高的精度后再进行转换: ```cpp double originalValue = 123456789.123456789; QString str = QString::number(originalValue, 'f', 15); // 设置15位小数 double convertedValue = str.toDouble(); qDebug() << "Original Value:" << originalValue; qDebug() << "Converted Value:" << convertedValue; ``` 通过这种方式,可以在转换前后保持较高的精度[^1]。 #### 3. 避免不必要的中间转换 尽量减少从 `double` 到 `QString` 再回到 `double` 的中间转换次数。每次转换都可能引入舍入误差。如果必须进行多次转换,建议始终使用相同的精度设置以减少误差累积。 #### 4. 使用 C 标准库函数进行手动转换 对于需要极高精度的情况,可以考虑使用 C 标准库中的 `strtod` 函数进行手动转换。这种方法绕过了 Qt 的内部实现,从而可能获得更高的精度: ```cpp #include <cstdlib> QString str = "123456789.123456789"; char *endPtr; double num = std::strtod(str.toUtf8().constData(), &endPtr); if (*endPtr == '\0') { qDebug() << "Converted number:" << num; } else { qDebug() << "Conversion failed"; } ``` 这种方法直接利用底层的 C 库函数,避免了 Qt 层面的潜在问题[^3]。 #### 5. 数据库字段设计注意事项 如果涉及数据库操作,应特别注意字段类型的定义。对于需要高精度的数值,建议使用 `DECIMAL` 或 `NUMERIC` 类型而非 `FLOAT` 或 `DOUBLE`,因为后者在存储时可能存在精度损失。例如,在 SQLite 中定义字段时: ```sql CREATE TABLE ExampleTable ( id INTEGER PRIMARY KEY, value DECIMAL(18, 9) -- 总共18位,小数点后9位 ); ``` 这样可以确保数据在存储和读取过程中保持高精度[^4]。 ### 示例代码 以下是一个完整的示例,展示如何在转换过程中避免精度损失: ```cpp QString str = "123456789.123456789"; QLocale locale(QLocale::English, QLocale::UnitedStates); bool ok; double num = locale.toDouble(str, &ok); if (ok) { qDebug() << "Converted number:" << num; } else { qDebug() << "Conversion failed"; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值