获取字符串数字的精度

Getting the precision of a string number

我正在从文本文件中读取值并将它们转换为双精度值, 然后,我需要在屏幕上打印这些值, 它们看起来应该与文本文件中的完全一样。

目前,我在打印时使用的是最大精度, 我可能会得到这样的结果:

文本值:8.994279313857e-317 打印值:8.99427931385706e-317

每个文本文件可能有不同的精度, 甚至不同值的不同精度(在同一个文本文件中), 出于内存考虑,我无法将这些值存储为字符串。

我的想法是用另一个 unsigned int 将它们存储为 double 以确保精度, 有没有办法从字符串数字中获取精度?

蛋糕不能自己吃! :)

我的意思是,您想要数字中字符串的精确表示,而不必支付内存方面的成本(只需存储字符串*)。

所以在那种情况下,你能做的最好的事情就是使用 long double,你知道我们在数字常量末尾附加的 L。然而,当然这也有其局限性(..因为我们的计算机也有局限性)。此外,对不需要的数字使用 space(和处理时间)会是多么浪费,因为您说您将达到的精度不是固定的。所以,你可以用那个代码来做到这一点(由 this and this answers and the std::numeric limits 亲切地组装):

#include <fstream>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <limits>

typedef std::numeric_limits< double > dbl;

int main() {
    std::ifstream ifile("example.txt", std::ios::in);
    std::vector<long double> scores;

    //check to see that the file was opened correctly:
    if (!ifile.is_open()) {
        std::cerr << "There was a problem opening the input file!\n";
        exit(1);//exit or do additional error checking
    }

    long double num = 0.0;
    //keep storing values from the text file so long as data exists:
    while (ifile >> num) {
        scores.push_back(num);
    }

    std::cout.precision(dbl::max_digits10); // you can print more digits if you like, you won't the exact representation obviously
    //verify that the scores were stored correctly:
    for (int i = 0; i < scores.size(); ++i) {
        std::cout << std::fixed << scores[i] << std::endl;
    }

    return 0;
}

在我的机器上:

C02QT2UBFVH6-lm:~ gsamaras$ cat example.txt 
3.12345678912345678912345678 2.79
C02QT2UBFVH6-lm:~ gsamaras$ g++ -Wall main.cpp
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
3.12345678912345679
2.79000000000000000

如果你想更进一步,那就用GMP,也就是"a free library for arbitrary precision arithmetic"。当然,这在内存使用和处理时间方面不会是免费的,所以你在使用它之前真的要三思


*我觉得你是过早优化的受害者。如果我是你,我会只存储字符串并看看这是怎么回事,或者更好的是使用数字数据类型,从而失去一些精度,让你的生活更轻松。当项目准备就绪时,查看您获得的结果以及所达到的精度是否令人满意 "your boss"。如果不是,请使用字符串(或 )。

正确的方法是使用一些 class 忠实地代表任何数值。要表示此类值,您可以使用带比例因子的任意精度整数 class。例如,可以这样定义:

#include <boost/multiprecision/cpp_int.hpp>

// numeric = value/pow(10, scale)
struct numeric {
  /// arbitrary precision integer
  boost::multiprecision::cpp_int value;
  /// point position
  int scale;
};
// for example, 10.1 can be represented with the numeric class exactlty in difference to double :
numeric n{101, 1}; // 101/pow(10, 1)

要打印这样的数字,您可以使用辅助函数将数字 class 的对象转换为 std::string:

std::string to_string(const numeric& n)  const
{
  if (n.value.is_zero() && n.scale <= 0)
    return "0";
  bool neg = n.value < 0;
  std::string r;
  {
    std::ostringstream s;
    s << (neg ? -n.value : n.value);
    s.str().swap(r);
  }
  if (n.scale > 0) {
    if (n.scale >= r.length()) {
      r = std::string(n.scale - r.length() + 1, '0') + r;
    }
    r.insert(r.length() - n.scale, 1, '.');
    if (neg)
      r = '-' + r;
  }
  else if (n.scale < 0) {
    if (neg)
      r = '-' + r;
    r += std::string(-n.scale, '0');
  }
  else {
    if (neg)
      r = '-' + r;
  }
  return std::move(r);
}

要从 std::string 构建数字对象,您可以找到点位置(即数字的比例),删除点并初始化 cpp_int 并从点字符串中清除。