获取字符串数字的精度
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"。如果不是,请使用字符串(或 gmp)。
正确的方法是使用一些 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 并从点字符串中清除。
我正在从文本文件中读取值并将它们转换为双精度值, 然后,我需要在屏幕上打印这些值, 它们看起来应该与文本文件中的完全一样。
目前,我在打印时使用的是最大精度, 我可能会得到这样的结果:
文本值: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"。如果不是,请使用字符串(或 gmp)。
正确的方法是使用一些 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 并从点字符串中清除。