关于浮点的一些问题

时间:2010-10-06 16:10:45

标签: c++ floating-point floating-accuracy

我想知道一个数字是否在浮点表示中以单向表示,它是否会在具有更大尺寸的表示中以相同的方式表示。 也就是说,如果某个数字的特定表示形式为float,那么如果将float强制转换为double,它是否具有相同的表示形式,然后在转换为{long double时仍然相同{1}}。

我想知道因为我正在写一个BigInteger实现和传入的任何浮点数我发送给一个接受long double转换它的函数。这引出了我的下一个问题。显然浮点并不总是具有精确的表示,所以在我的BigInteger类中,当给定浮点数时我应该尝试表示什么。尝试表示std::cout << std::fixed << someFloat;给出的相同数字是否合理,即使这与传入的数字不同。这是否是我能得到的最准确的表示?如果是这样,......

提取该值的最佳方法是什么(以10的幂为基础),此时我只是将其作为字符串抓取并将其传递给我的字符串构造函数。这样可行,但我不禁觉得这是一个更好的方法,但当我用基数划分时,肯定会拿下余数,这对浮点数来说并不准确。

最后,我想知道是否存在等价于uintmax_t的浮点数,这是一个始终是系统中最大浮点类型的类型名称,或者没有意义,因为long double将会永远是最大的(即使它与双倍相同)。

谢谢,T。

3 个答案:

答案 0 :(得分:9)

如果通过“相同表示”表示“除了填充之外,内存中的二进制表示完全相同”,则表示没有。双精度具有指数和尾数的更多位,并且还具有不同的指数偏差。但我相信任何单精度值都可以用双精度表示(除了可能的非规范化值)。

当你说“浮点并不总是有确切的表示”时,我不确定你的意思。当然,并非所有十进制浮点值都具有精确的二进制浮点值(反之亦然),但我不确定这是一个问题。只要您的浮点输入没有小数部分,那么适当大的“BigInteger”格式应该能够准确地表示它。

通过基础10表示的转换不是要走的路。理论上,您只需要一个长度为~1024的位数组,将其全部初始化为零,然后将尾数位移入指数值。但是,如果不了解您的实施情况,我可以提出更多建议!

答案 1 :(得分:2)

double包含float的所有值; long double包含double的所有值。因此,您不会通过转换为long double而丢失任何有价值的信息。但是,您丢失了有关原始类型的信息,这是相关的(见下文)。

为了遵循常见的C ++语义,将浮点值转换为整数应截断该值,而不是舍入。

主要问题是大的值不准确。您可以使用frexp函数查找浮点值的基数2指数。您可以使用std::numeric_limits<T>::digits检查是否在可以准确表示的整数范围内。

我的个人设计选择是断言fp值在可以精确表示的范围内,即对任何实际参数范围的限制。

要做到这一点,你需要使用floatdouble参数进行重载,因为可以精确表示的范围取决于实际参数的类型。

当你的fp值在允许的范围内时,你可以使用floorfmod来提取你想要的任何数字系统中的数字。

答案 2 :(得分:0)

是的,从IEEE float到double再扩展,您将看到从较小格式到较大格式的位,例如

single
S EEEEEEEE MMMMMMM.....
double 
S EEEEEEEEEEEE MMMMM....

6.5 single
0 10000001 101000...
6.5 double
0 10000000001 101000...
13 single
0 10000010 101000...
13 double
0 10000000010 101000...

您将左对齐尾数,然后添加零。

指数是右对齐,符号扩展到msbit旁边然后复制msbit。

例如指数为-2。取-2减1,即-3。二进制补码中的-3为0xFD或0b11111101,但格式中的指数位为0b01111101,msbit为反转。并且对于双a -2指数-2-1 = -3。或0b1111 ... 1101,变为0b0111 ... 1101,msbit反转。 (指数位= twos_complement(exponent-1),msbit反转)。

如上所述,指数为3 3-1 = 2 0b000 ... 010反转高位0b100 ... 010

所以是的,您可以从单精度中获取位并将它们复制到双精度数中的适当位置。我没有一个扩展的浮动参考方便,但很确定它的工作方式相同。