获得字符串数字的精度

时间:2016-07-20 18:57:12

标签: c++ precision

我正在从文本文件中读取值并将其转换为双精度数, 那么,我需要在屏幕上打印这些值, 它们应该与文本文件中的完全相同。

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

文字值:8.994279313857e-317 印刷值:8.99427931385706e-317

每个文本文件可能具有不同的精度, 或者甚至是不同值的不同精度(在同一文本文件中), 而且我不能将这些值存储为内存关注的字符串。

我的想法是将它们作为双精度存储在另一个无符号整数中以保证精度, 有没有办法从字符串数字中获取精度?

2 个答案:

答案 0 :(得分:0)

你不能吃蛋糕而且也吃它!:)

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

因此,在这种情况下,您可以做的最好的事情是使用long double,您知道我们在数字常量末尾附加的L。然而,当然这也有其局限性(因为我们的计算机也有限制)。而且,对于不需要的数字,使用long double会浪费空间(和处理时间),因为你说你将遇到的精度不固定。所以,您可以使用该代码执行此操作(由thisthis答案以及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,这是“任意精度算术的免费库”。当然,这在内存使用和处理时间方面不会是免费的,所以在使用之前你应该真的三思而后行

* 我觉得你是过早优化的受害者。如果我是你,我会存储字符串,看看它是如何发展的,或者更好地使用数字数据类型,从而失去一些精确度,使你的生活变得更加容易。当项目准备就绪时,看看你得到了什么结果,如果达到的精度令“你的老板”高兴。如果没有,请使用字符串(或)。

答案 1 :(得分:0)

正确的方法是使用某些类忠实地表示任何数值。要表示此类值,可以使用具有比例因子的任意精度整数类。例如,它可以定义如下:

#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)

要打印此类数字,您可以使用帮助函数将数字类的对象转换为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构造数值对象,您可以找到点位置(即数字的比例),从点字符串中清除点和init cpp_int。