C++ 从float中删除小数部分但保留类型的有效方法
我知道通过std::round、std::floor或std::ceil或简单的类型转换,我们可以删除小数部分,但是通过类型转换,变量会丢失其原始类型(float或double) 有没有办法,我可以保留类型,但仍然有效地删除小数部分 我认为其中一种方法是从数字中减去小数部分,但效率不高。那么,也许还有其他方法 范例-C++ 从float中删除小数部分但保留类型的有效方法,c++,floating-point,C++,Floating Point,我知道通过std::round、std::floor或std::ceil或简单的类型转换,我们可以删除小数部分,但是通过类型转换,变量会丢失其原始类型(float或double) 有没有办法,我可以保留类型,但仍然有效地删除小数部分 我认为其中一种方法是从数字中减去小数部分,但效率不高。那么,也许还有其他方法 范例- float a = 123.456; float b; b = do something on a; 结果b为123.0例如,使用std::round保留原始类型: floa
float a = 123.456;
float b;
b = do something on a;
结果b为123.0例如,使用
std::round
保留原始类型:
float round(float arg);
double round(double arg);
这同样适用于std::floor
和std::ceil
添加。以下是一些基准测试结果
Compiler raw loop std::ceil std:floor std::trunc std::round
--------------------------------------------------------------------
gcc 8.36 8.20 8.19 8.21 32.95
gcc(f) 2.88 8.20 8.20 8.20 11.01
msvs 8.20 28.47 31.90 67.14 97.84
msvs(f) 8.13 13.70 14.00 67.27 97.50
坦率地说,我不认为这些结果本身就非常相关(绝对值)。使用“快速数学”选项,某些函数仅简化为一条汇编指令。应分析真实代码以获得相关结果。请检查:
为什么你不能先转换成int,然后再转换成float,让编译器来处理呢?@MeetTitan这真是麻烦。
float
的范围远大于int
@MeetTitan[conv.fpint]
“浮点型prvalue可以转换为整型prvalue。转换截断;也就是说,小数部分被丢弃。如果目标类型中无法表示截断的值,则行为未定义。“b=(int)a、
应该可以。@melpomene,不是在粒度上。如果你取一个32位浮点,并尝试将其赋值为一个32位的整数左值,你可能会感到惊讶……这远远低于32位整数类型的范围。在我的例子中,由于缺少有效位,我得到了1000000128
s在浮点中,在整数对应项中使用。:)哦..那很简单..我不知道round/floor/ceil保留了该类型。但有意义。这实际上是比公认的答案“更大”的答案,我想。@RudyVelthuis为什么?它没有回答标题中的问题(如何删除数字的小数部分)@RudyVelthuis-好吧,问题是要有效地删除分数部分,因为它将被使用的数据集是巨大的。我没有进行基准测试,但我强烈认为trunc将在其他参赛者中获胜。我已经将主题行更改为更具体。@Infoblock在回答问题后请不要更改您的问题;如果您你有一个新问题,把它当作一个新问题来问。答案很好。trunc和modf与round有什么区别(我现在知道,那一轮保留了这个类型)?@infoblockround
将整数舍入最接近的整数(远离0),例如round(0.7)
是1.0
,但是trunc(0.7)
是0.0
(它只是去掉了小数部分)。看起来trunc真的很笨,应该是所有方面中最快的,ceil,floor等等。这对我来说很有用。@InfoBulled:trunc()不是“笨”。将FP值转换为整数值需要一些工作,这与floor()或ceil()甚至round()的工作是一样的@melpemone:哪些位/多少位?但你没有将某些位设置为0。你必须知道可以删除多少位,然后必须舍入到最后一个剩余位的位置,然后对结果进行规范化。这比只删除一些位要多一些工作。但通常在硬件中是这样,所以没什么大不了的。
gcc: --std=c++17 -O3 -m64 -march=native -fno-tree-vectorize
gcc(f): --std=c++17 -O3 -m64 -march=native -ffast-math -fno-tree-vectorize
msvs: /fp:precise /fp:except /O2 /std:c++latest ...
msvs(f): /fp:fast /fp:except- /O2 /std:c++latest ...
#include <cmath>
float a = 123.456;
float b, c;
c = std::modf(a, &b);
// c = 0.456
// b = 123.0
float b = std::trunc(a);