浮动为字符串而不四舍五入

时间:2019-05-15 09:41:04

标签: c++ string floating-point rounding precision

我想从十进制数字中提取小数位。不是那么难,对吧?

因此,我将float转换为字符串。

然后,我用substr()裁剪了从string.find('.')+1到结尾的字符串。

好吧...问题出在这里。当我们有一个这样的数字:5.7741589时,它并不是那么“精确”,实际上是:5.774159

如果它本身是四舍五入的,我将无法精确获得小数位数...所以问题是:

如何将十进制数字转换为字符串而不进行四舍五入?

编辑:由于很多人都在要求实际的输入,输出和代码,所以这里是:

Input: 5.7741589
Output (let's say we want to output just decimal places): 7741589
Output (not expected one): 774159

代码:

float num;
cin>>num;
string s = to_string(num);
s = s.substr(s.find('.')+1,s.length());
cout<<s<<endl;

EDIT2:还有一件事。对于竞争性编程,我需要这样做,我可以使用输入作为字符串来完成此练习。想象一下,如果您有2个十进制数字,您需要将它们相乘,然后计算小数位数,那么您会遇到问题。然后您又失去了小数位,这是有问题的。

3 个答案:

答案 0 :(得分:4)

使用二进制浮点数对十进制数建模时,腐烂就会出现:浮点方案对实数的子集进行建模。在这方面,使用整数类型没有什么不同:从概念上讲,出现的问题没有什么不同。

如果要精确建模十进制数字,请使用十进制类型。

答案 1 :(得分:1)

您得到的结果是因为四舍五入到小数位。这是因为,一旦输入浮点数(无论是小数位数),它就会存储为与数据类型的精度一样多的小数位数。因此对于浮点数(可以存储8位小数),如果输入

1.1234      ---- Stored as ---> 1.12339997
1.123       ---- Stored as ---> 1.12300003
5.7741589   ---- Stored as ---> 5.77415895

因此,基本上,您将输入存储在小数位数(8)中。可以做的是,您可以使用下面的代码段强制使用小数点后的所需位数并将其转换为字符串。

float num;
cin >> num;

char buf[20];

// 8 is as per the (precision required + 1). So in this case,
// we have 7 digits after decimal, so 8 is used.
sprintf(buf, "%.8f", num); 

// Truncating the rounding off
buf[strlen(buf) - 1] = '\0';

string s(buf);
s = s.substr(s.find('.') + 1, s.length());
cout << s << endl;  

尽管采用这种方法,但所有输入的小数位数必须相等。

这是一种解决方法,因为您输入的值5.7741589不会按原样存储。因此,如果源本身不是您输入的内容,那么假设源是您提供的 ,那么如何获得所需的输出。

答案 2 :(得分:1)

让我们看看会发生什么(这个答案假设IEEE-754,浮点数是32位二进制浮点数)。

首先,输入十进制数字作为输入:5.7741589。此数字必须存储在32位 binary 浮点中。

此二进制数字是101.11000110001011110100011100010101011010000100011 ...

要将其存储为浮点数,我们需要将其舍入(以二进制形式)。因此cin>>num有损。舍入到最接近的32位二进制浮点数,即:

  • 二进制:1.01110001100010111101001 * 2 ^ 2 = 101.110001100010111101001。
  • 以十进制表示的:1.44353973865509033203125 * 2 ^ 2 = 5.774158954620361328125。

正如您所看到的,在您将输入数字转换为浮点数之后,毫无意义地谈论小数位,因为您的输入数字已被修改(以二进制形式查看数字,四舍五入。将数字看成十进制数,它会得到很多额外的数字,其值与原始数字略有不同。

如果要解决此问题,则需要输入数字作为字符串,或者需要使用某种 decimal 浮点库。