如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
How to keep c++ from adding extra decimals when casting from float to double (not for IO)?
我面临的问题是因为我正在使用一个库,当输入float
时,它会在内部执行一些操作,将浮点数转换为双精度并将许多小数添加到不正确的数字中。我的意思是,根据双精度和浮点数的表示方式以及投掷时自然发生的情况是正确的,但这不适合我的应用程序。我有16.3
float
,我需要像double
一样16.3
。
我正在尝试在将值传递给库以控制该转换之前将浮点数转换为双倍 U,但到目前为止,我还没有找到一种直接的方法。我只想知道是否有可能将 16.3 从float
投到double
并因此获得相同的 16.3。
float f_var = 16.3; // f_var is 16.3
double d_var = (double)f_var; // d_var shall be also 16.3, not 16.299999237060547
在C++中甚至有适当的方法来做到这一点吗?或者我将不得不做这样的事情:
char float_buf[10];
float f_var = 16.3;
sprintf(float_buf, "%.2f", f_var);
double d_var = atof(float_buf);
因为这有效,但我想看看在 c++ 中是否有一种"适当"的方法。
SO中有另一个建议的解决方案的响应,但它涉及乘法和除法,我也想避免。
这不是为了显示或任何输入/输出操作或转换为字符串,我知道该怎么做,并且有很多关于它的信息。此外,我并不是想理解"为什么"会发生这种情况,也有很多关于这方面的信息。
此外,SO中可能导致此问题标记为重复的大多数答案都不适用于C++,它们主要针对C#,Java JS,Objective C等。对于我为 C/C++ 找到的少数几个,他们中的大多数都在用printf
或cout
处理 IO 的这个问题,其他人只解释为什么会发生这种情况,这也是没有用的。如果您确实在C++中对此有副本,请注明。如果真的是,我会很高兴将其标记为重复。
谢谢!
这个答案假设IEEE浮点数。
机器数据类型(如float
)包含有限数量的位,因此只能表示有限数量的值。唉,16.3
碰巧不是其中之一。
float f_var = 16.3;
f_var
的值现在是 (1) 可表示为单个精度浮点数和 (2) 尽可能接近16.3
的数字。这个数字恰好是16.299999237060546875
。这是最接近16.3
的一个。下一个较大的可表示数是16.3000011444091796875
,它离得更远。如果您好奇,这两个二进制表示是01000001100000100110011001100110
和01000001100000100110011001100111
的。它们仅在最后一点不同。
double d_var = (double)f_var;
你瞧,d_var
的值现在是完全相同的数字16.299999237060546875
。
这是最接近16.3
的可能double
数字吗?地狱不!
double
可以准确地表示16.300000000000000710542735760100185871124267578125
,它更接近16.3
然后16.299999237060546875
。
但是d_var
为什么要采用这个更精确的值呢?它已经16.299999237060546875
显示,现在它非常忠实地16.299999237060546875
。如果希望它更精确,请为其分配一个更精确的值。它不是有情众生,也不知道你的意思是16.299999237060546875
16.3
。
从哪里可以得到如此精确的值?
好吧,人们可以任意决定所有有趣的数字在小数点后不超过一位数字,并且在此之后有无限个零。(为什么人们会认为这超出了我的范围,但我正在玩)。如果是这种情况,那么
d_var = round(d_var * 10)/10
会将数字四舍五入为非常接近小数点后有一个十进制数字的数字,以及无限个零的数字。如果我们用16.299999237060546875
做这个技巧,它会变得16.300000000000000710542735760100185871124267578125
。
如果您对小数点后两位数的数字感兴趣,请将 10 替换为 100,依此类推。但是,在这一点上,您应该问问自己浮点类型是否是适合这项工作的工具。也许您需要定点十进制数?
另一方面,如果您对最初具有任何位数的数字感兴趣,那么您必须提供该位数,并可能将其与数字本身一起记住。在这一点上,你应该更加努力地问自己上述问题。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 如何在C++中从两个单独的for循环中添加两个数组
- Seg Fault Issue C++ (file IO / getline)
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 如何仅为一个函数添加延迟
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 使用std::transform将一个范围的元素添加到另一个范围中
- 如何将更多文件夹添加到c++include路径
- 如何将元素添加到数组的线程安全函数?
- QT通过C++添加映射QML项目
- 为什么在读取文件大小时文件IO速度会发生变化
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 只能向C++添加一定数量的字符
- Qt和C++:将QLineEdit添加到QTabWidget中
- 将QIcon添加到QTableView单元格
- 为什么我必须在C++中添加一个赋值符号来声明一个数组
- 为什么除非添加括号,否则构造函数上的模板替换会失败?