【问题标题】:How to accurately display and store and use data exactly up to certain number of decimal places in C++?如何在 C++ 中准确地显示、存储和使用精确到一定小数位数的数据?
【发布时间】:2021-04-17 00:16:37
【问题描述】:

如果我有一个double 变量,我想使用标准的四舍五入规则将它的值存储到一个文件中的小数点后两位。我不仅想存储和显示最多两位小数的数据,而且我还想使用这些数据进行算术运算,当我重新打开文件时,精确到两位小数。换句话说,当我将文件中的这些数据读入double 变量时,我希望这些数据也能准确地加载到小数点后两位,就像我存储它一样。到目前为止,使用<iomanip>fixedsetprecision 仅用于显示与std::cout 一起使用的输出。不过我可能是错的。请使用以下示例说明如何完成此操作?另外如何将来自double 变量的数据存储到binary 文件中的小数点后两位?

std::ofstream file("data.txt");
int hours = 8, mins= 35;
char ap='p';

double format_24_hr=0.00;
format_24_hr = static_cast<double>(hours) + 12.00 + static_cast<double>(mins)/60.00;
file<<format_24_hr;  // how to store double to two decimal places in a binary file
file.close();

另外,当我像下面这样读取文件时,如何确保它加载的数据与我存储的数据完全相同?

std::ifstream file("data.txt");
double var=0.00;
file>>var;   // would the data read here be exactly loaded to two decimal places as I stored it?
file.close();

【问题讨论】:

  • 你所要求的在物理上是不可能的。基于二进制的doubles 不能准确地保存所有十进制值。
  • 更具体地说,您可以准确存储4.25,但最接近4.26 的是4.2599999999999997868371792719699442386627197265625
  • 将数据存储/读取为“原始”值的 100 倍的 整数 值。
  • 当您的所有需求都达到fixed-point 表示时,为什么要将您的值存储在浮点 表示中?您可以更改变量的类型吗?
  • 查看Is floating point math broken?,看看它是否能让事情变得更清楚。

标签: c++ double precision


【解决方案1】:

您所描述的是fixed point 表示。尝试对定点值使用浮点表示通常会导致问题,正如您所发现的那样,如Is floating point math broken? 中所述,有关表示的更详细比较,请参阅Fixed point vs Floating point number

一种合理(有时也很简单,取决于您的需要)的方法是使用整数来表示您的值。您可以围绕这个整数构建一个界面,以便在查看时将其除以 100,使其看起来像一个小数点后两位数的数字。也就是说,如果存储的值为2058,则使用该值的代码将看到(最接近的double 值)20.58。这是一个起点的例子:

class FixedPoint {
    int value;

public:
    double get() const { return static_cast<double>(value) / 100.0; }
    // Also define other needed functionality, including arithmetic.
    // Multiplication and division require a bit of care.
};

但是您的示例代码尝试将小时和分钟存储为小数小时。这已经是有问题的了,因为这种关联并不精确。例如,你不能从整数小时和分钟中得到20.58小时;你可以接近 (20.58333333...),但不完全是。

比小数小时更一致的方法是总分钟数。而不是存储

static_cast<double>(hours) + 12.00 + static_cast<double>(mins)/60.00

到一个文件并处理精度问题,你可以通过存储获得完美的精度

(hours + 12) * 60 + mins

这是一个整数,回避了使用多少小数位的问题。读取保存的值时将恢复完全相同的值。

保存小数小时以供人类可读的输出(如果需要),并将总分钟数用于需要由您的程序存储和检索的值。

【讨论】:

  • 完美答案。太感谢了。很抱歉回复晚了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
相关资源
最近更新 更多