gpt4 book ai didi

c++ - 设置精度无法正常工作

转载 作者:太空宇宙 更新时间:2023-11-04 15:23:19 24 4
gpt4 key购买 nike

#include <iostream>
using namespace std;

int main()
{
cout.precision(50);
cout<<"Anmol's Square Root Calculator!"<<endl;
cout<<""<<endl;
cout << "This program will compute the square root\n";
cout << "of a number using the Babylonian algorithm!\n";
cout<<""<<endl;
cout<<"Only positive numbers work with this algorithm!"<<endl;
cout<<""<<endl;
cout<<"All cycle #1 approximate square roots are guessed\n"<<"using 1 as the first approximate."<<endl;
cout<<""<<endl;
cout<<""<<endl;
cout<<""<<endl;



char playAgain='y';
while (playAgain !='n')
{
int count(25), cycle(1);
double guess, sqrt, num;
cout << "Please enter the number you would like to compute the square root of: ";
cin >> num;
cout<<""<<endl;

do {
if (num <= 0)
{
cout<<""<<endl;
cout<<"Invalid input. Please re-enter a valid number: ";
cin >> num;
cout<<""<<endl;
}
} while (num <= 0);

cout<<""<<endl;
cout<<""<<endl;
cout<<""<<endl;

for (guess=1; count!=0; count--)
{
guess =(guess + (num/guess))/2;
cout<<""<<endl;
cout<<"Cycle "<<cycle<<" Aproximate: "<<guess<<endl;
sqrt = guess;

cycle++;
}

cout<<""<<endl;

cout << "The square root of "<< num << " is " << sqrt<<"!"<<endl;;
cout <<""<< endl;

do {
cout <<""<<endl;
cout << "Would you like to calculate again? (y/n): ";
cin >> playAgain;
cout <<" "<<endl;
do {
cout <<""<<endl;
if ((playAgain !='y' && playAgain !='n'))
{
cout << "Invalid input. Only y/n: ";
cin >> playAgain;
cout <<" "<<endl;
}
} while (playAgain !='y' && playAgain !='n');

} while (playAgain !='y' && playAgain !='n');

}

cout<<"Thank you for using a program made by Anmol Sethi!"<<endl;
cout<<""<<endl;
cout<<""<<endl;
cout<<""<<endl;
cin.get();
return 0;
}


对于我的数学课,我们正在学习平方根。根据我的老师的说法,唯一可能的方法是使用计算器或表格来查找平方根,这显然是错误的,因为计算器需要一种计算平方根的方法。经过广泛研究,我使用巴比伦算法编写了此代码。但是我面临一个问题
在此代码中,我专门将小数的精度设置为15。但是,它输出的数字为12个小数。但是在此代码中,它以15位小数输出。

#include <iostream>
using namespace std;

int main()
{
cout.precision(18);
cout<<"Anmol's Square Root Calculator!"<<endl;
cout<<""<<endl;
cout << "This program will compute the square root\n";
cout << "of a number using the Babylonian algorithm!\n";
cout<<""<<endl;
cout<<"Only positive numbers work with this algorithm!"<<endl;
cout<<""<<endl;
cout<<"All cycle #1 approximate square are guessed\n"<<"using 1 as the approximate."<<endl;
cout<<""<<endl;
cout<<""<<endl;
cout<<""<<endl;
char playAgain='y';
while (playAgain !='n')
{
int count(25), cycle(1);
double guess(1), sqrt, x, num;
cout << "Please enter the number you would like to know the square root of: ";
cin >> num;
cout<<""<<endl;

do {
if (num <= 0)
{
cout<<""<<endl;
cout<<"Invalid input. Please re-enter a valid number: ";
cin >> num;
cout<<""<<endl;
}
} while (num <= 0);

cout<<""<<endl;
cout<<""<<endl;
cout<<""<<endl;

while (count > 0)
{
x = guess =(guess + (num/guess))/2;
cout<<""<<endl;
cout<<"Cycle "<<cycle<<" Aproximate: "<<guess<<endl;
sqrt = guess;

count-=1;
cycle+=1;
}

cout<<""<<endl;
cout<<""<<endl;
cout<<""<<endl;
cout << "The sqaure root of "<< num << " is " << sqrt<<"!"<<endl;;
cout <<""<< endl;

do {
cout <<""<<endl;
cout << "Would you like to calculate again? (y/n): ";
cin >> playAgain;
cout <<" "<<endl;

do {
cout <<""<<endl;
if ((playAgain !='y' && playAgain !='n'))
{
cout << "Invalid input. Only y/n: ";
cin >> playAgain;
cout <<" "<<endl;
}
} while (playAgain !='y' && playAgain !='n');

} while (playAgain !='y' && playAgain !='n');

}

cout<<"Thank you for using a program made by Anmol Sethi!"<<endl;
cout<<""<<endl;
cout<<""<<endl;
cout<<""<<endl;
cout<<""<<endl;
cin.get();
return 0;

}


我对为什么会这样感到非常困惑。我尝试了cout <<固定<< showpoint;但是当num无缘无故地输出15个零时,它看起来不愉快。谁能启发我为什么会这样以及如何解决?在书中,我读到将for循环用于算法更为有效,因此我想使用for而不是while循环。我还有第二个问题。为什么我不能超过15位小数?如果将精度设置为30/40,即使对我的计算机计算器来说,精度也变为30/40,但对我的输出没有任何作用。我应该使用另一个整数类型而不是double吗?

抱歉,如果其中任何内容看起来像是xD的大墙。

我急于键入此错误,这对我来说是上午12:05的atm。

先谢谢了

ps我现在要在这个论坛上发表很多文章。大约一年前,我曾经大量使用它,但是我退出了c ++编程一段时间,因为当我使用较小的xD时,我无法进一步理解它。因此,即时通讯我现在正在为此读书,希望我能从控制台应用程序一直到Windows。如果有问题,我正在使用Visual Studio Ultimate 2012。 xD

最佳答案

首先,欢迎使用StackOverflow!我相信您在学习编程时会发现它是宝贵的资源。也就是说,要充分利用该网站,务必遵守the site's guidelines。通常,请记住,SO不是论坛而是Q&A站点,您会做的很好。



一般问题

您发布的代码存在一些问题:

A.空格

对于其他程序员和您自己而言,使用whitespacemaking your code legible and intelligible都是非常有用的。 Tabbing to indicate scope(写作

bool condition = ...
if (condition) {
action();
}


而不是

bool condition = ...
if (condition) {
action()
}


(这并不表示操作范围),大大提高了可读性,尤其是在您发布的代码中有多个 nested scopes的情况下。 Spacing也很重要。

B.使用 cout

1.只需编写 cout << "" << endl,而不是编写 cout << endl

2.differences between endl and "\n",并且从您的代码中可能会发现它们。尽管使用两者的性能特征并不相同,但考虑到在此阶段肯定是 premature optimization。对于这种记录,坚持使用 endl更具可读性。而不是

cout << "All cycle #1 approximate square are guessed\n" << "using 1 as the approximate." << endl;


最好写

cout << "All cycle #1 approximate square are guessed" << endl << "using 1 as the approximate." << endl;


在这种情况下。

3.如果您的 inserting int cout远远超出一行代码(此代码,

cout << "This line of code is longer than feels comfortable." << endl << "It would be much more pleasant to break this into several lines so that I don't need to scroll to the right to view the whole thing." << endl;


例如,对于一行来说太长了),而不是像您的代码中那样,

cout << "Anmol's Square Root Calculator!" << endl;
cout << endl;
cout << "This program will compute the square root\n";
cout << "of a number using the Babylonian algorithm!\n";
cout << endl;
cout << "Only positive numbers work with this algorithm!" << endl;
cout << endl;
cout << "All cycle #1 approximate square are guessed\n" << "using 1 as the approximate." << endl;
cout << endl;
cout << endl;
cout << endl;


多次使用 cout上的插入运算符,您可以编写

cout << "Anmol's Square Root Calculator!" << endl
<< endl
<< "This program will compute the square root" << endl
<< "of a number using the Babylonian algorithm!" << endl
<< endl
<< "Only positive numbers work with this algorithm!" << endl
<< endl
<< "All cycle #1 approximate square are guessed" << endl
<< "using 1 as the approximate." << endl
<< endl
<< endl
<< endl;


C.模块化

您所有的代码都在 main()中。即使使用如此短的程序,仍然会影响可读性。更重要的是,这意味着您无法在其他地方重复使用此程序中创建的功能。

一个好的方法是将您的程序分解为单独的组件。在此程序中,您具有以下设置:

show a greeting
do {
get number from user
compute the squareroot of that number while logging
show the user the squareroot
ask the user if they want to do another computation
} while the user wants the program to keep running
show a farewell


此时,您可以为每个步骤编写函数。我在这里“编写”的功能是从您的代码中摘录而来,并做了一些很小的修改。

打印到屏幕

向用户显示问候和告别的功能是最简单的,因为它们(几乎)只需要使用 cout即可:

void showGreeting()
{
cout << "Anmol's Square Root Calculator!" << endl
<< endl
<< "This program will compute the square root" << endl
<< "of a number using the Babylonian algorithm!" << endl
<< endl
<< "Only positive numbers work with this algorithm!" << endl
<< endl
<< "All cycle #1 approximate square are guessed" << endl
<< "using 1 as the approximate." << endl
<< endl
<< endl
<< endl;
}

void showFarewell()
{
cout << "Thank you for using a program made by Anmol Sethi!" << endl
<< endl
<< endl
<< endl;
cin.get();
}


获取用户输入

接下来,我们需要一个函数来从用户那里获取号码

double getInputNumber()
{
double num = 0.0f;

cout << "Please enter the number you would like to compute the square root of: ";
cin >> num;
cout << endl;

do {
if (num <= 0)
{
cout << endl
<< "Invalid input. Please re-enter a valid number: ";
cin >> num;
cout << endl;
}
} while (num <= 0);

cout << endl
<< endl
<< endl;

return num;
}


另外,我们需要确定用户是否希望程序再次运行。从程序的角度(从 main的角度来看),这是一个非常布尔的问题:我们应该调用某个函数,并且应该返回 truefalse。但是,在该功能内,我们正在与用户进行交互,因此使用 'y''n'是理想的选择(至少对于说英语的用户而言);

bool getRunAgain()
{
bool choice = false;

char playAgain = 'n';
do {
cout << endl
<< "Would you like to calculate again? (y/n): ";
cin >> playAgain;
cout << endl;
do {
cout << endl;
if ((playAgain !='y' && playAgain !='n'))
{
cout << "Invalid input. Only y/n: ";
cin >> playAgain;
cout << endl;
}
} while (playAgain !='y' && playAgain !='n');
} while (playAgain !='y' && playAgain !='n');

if (playAgain == 'y') {
choice = true;
} else /*if (playAgain == 'n')*/ {//At this, playAgain is either 'y' or 'n'. So if it's not 'y', it's 'n'.
choice = false;
}
return choice;
}


由于将此代码重写为一个函数,因此很容易看到这里要做的工作比必要的要多:考虑外部 do...while循环。其重复条件是 playAgain !='y' && playAgain !='n'。乍一看,这似乎是有道理的:我们需要确保用户输入的是“是”或“否”。但是请注意,内部 do...while循环的条件完全相同。这意味着除非 playAgain等于 'y''n',否则内部循环不会退出。因此,当我们离开内部循环时,可以确定 playAgain'y'还是 'n'。因此,我们无需再次检查。这使我们可以像下面这样重写函数:

bool getRunAgain()
{
bool choice = false;

char playAgain = 'n';
cout << endl
<< "Would you like to calculate again? (y/n): ";
cin >> playAgain;
cout << endl;
do {
cout << endl;
if ((playAgain !='y' && playAgain !='n'))
{
cout << "Invalid input. Only y/n: ";
cin >> playAgain;
cout << endl;
}
} while (playAgain !='y' && playAgain !='n');

if (playAgain == 'y') {
choice = true;
} else /*if (playAgain == 'n')*/ {
choice = false;
}
return choice;
}


但是在剩余的循环中,我们也有类似的情况:

do { 
cout << endl;
if ((playAgain !='y' && playAgain !='n'))
{
cout << "Invalid input. Only y/n: ";
cin >> playAgain;
cout << endl;
}
} while (playAgain !='y' && playAgain !='n');


除了 cout << endl不太重要之外,除非 (playAgain !='y' && playAgain !='n'),否则我们根本不想进入循环。这需要 while循环而不是 do...while循环:

while (playAgain !='y' && playAgain !='n')
{
cout << "Invalid input. Only y/n: ";
cin >> playAgain;
cout << endl;
}


将其放入我们的功能中,我们现在有了

bool getRunAgain()
{
bool choice = false;

char playAgain = 'n';
cout << endl
<< "Would you like to calculate again? (y/n): ";
cin >> playAgain;
cout << endl;

while (playAgain !='y' && playAgain !='n')
{
cout << "Invalid input. Only y/n: ";
cin >> playAgain;
cout << endl;
}

if (playAgain == 'y') {
choice = true;
} else /*if (playAgain == 'n')*/ {
choice = false;
}
return choice;
}


计算平方根

最后,我们需要一个使用巴比伦算法计算平方根的函数。我们只需要拿您的代码

int count(25), cycle(1);
double guess, sqrt, num;
cout << "Please enter the number you would like to compute the square root of: ";
cin >> num;
cout << endl;

for (guess=1; count!=0; count--)
{
guess =(guess + (num/guess))/2;
cout<<""<<endl;
cout<<"Cycle "<<cycle<<" Aproximate: "<<guess<<endl;
sqrt = guess;

cycle++;
}


并将其放入需要加倍并返回一个的函数中:

double computeSquareRootBabylonian(double num)
{
int count(25), cycle(1);
double guess, sqrt;

for (guess = 1; count != 0; count--)
{
guess = (guess + (num/guess))/2;
cout << endl
<< "Cycle " << cycle << " Aproximate: " << guess << endl;
sqrt = guess;

cycle++;
}
return sqrt;
}


我们可以在这里停止,但是可以进行一些更改以改善功能。

1.初始近似值(您正在使用的初始猜测 1)实际上不是此函数的一部分。调用此函数的代码应指定起始点:

double computeSquareRootBabylonian
(double num,
double initialApproximation)
{
double approximation, sqrt;
unsigned int count(25), cycle(1);

for (approximation = initialApproximation; count != 0; count--)
{
approximation =(approximation + (num/approximation))/2;
cout << endl
<< "Cycle " << cycle << " Aproximate: " << approximation << endl;
sqrt = approximation;

cycle++;
}
return sqrt;
}


2.迭代次数(或循环,正如您所称的)实际上也不是函数的一部分。调用此函数的代码必须指定该数字:

double computeSquareRootBabylonian
(double num,
double initialApproximation,
unsigned int iterations)
{
double approximation, sqrt;
unsigned int iterationsRemaining = iterations;
unsigned int iteration = 1;

for (approximation = initialApproximation; iterationsRemaining != 0; iterationsRemaining--)
{
approximation =(approximation + (num/approximation))/2;
cout << endl
<< "Cycle " << iteration << " Aproximate: " << approximation << endl;
sqrt = approximation;

iteration++;
}
return sqrt;
}


3.这个 for循环很奇怪。奇怪是因为您在初始化时初始化了变量 guess(我已将其重命名为 approximation),尽管它不是 "loop variable"。在第二段代码中,您使用了

while (count > 0)
{
guess =(guess + (num/guess))/2;
cout << endl;
cout << "Cycle " << cycle << " Aproximate: " << guess << endl;
sqrt = guess;

count-=1;
cycle+=1;
}


代替。这段代码的意图更加清晰,但是使用 for循环和 standard way可以使意图最清晰(在初始化中初始化相同的变量,循环的条件取决于该变量,并在每个循环的末尾进行更改)循环: for (int i = 0; i < 10; i++))。在这里被迭代的变量是 count(我称为 iterationsRemaining),并且只要用户指定的迭代次数( iterations参数)被递减了 1即可。它大于 0。这种情况需要以下for循环:

for (unsigned int iterationsRemaining = iterations; 
iterationsRemaining > 0;
iterationsRemaining--)
{
//...
}


将其替换为我们的函数时,我们需要确保仍将 approximation初始化为 initialApproximation

double computeSquareRootBabylonian
(double num,
double initialApproximation,
unsigned int iterations)
{
double approximation = initialApproximation;
unsigned int iteration = 1;
double sqrt;

for (unsigned int iterationsRemaining = iterations;
iterationsRemaining > 0;
iterationsRemaining--)
{
approximation =(approximation + (num/approximation))/2;
cout << endl
<< "Cycle " << iteration << " Aproximate: " << approximation << endl;
sqrt = approximation;

iteration++;
}
return sqrt;
}


撇开:过早的优化

你写了


  在书中,我读到将for循环用于算法更为有效,因此我想使用for而不是while循环。


这不是使用 for循环的好理由。您无需(在合理的范围内)更改代码以使其更快,除非您确定它的运行速度太慢。编写在阅读时有意义的代码更为重要。

4.变量 sqrt的作用是什么?它反复分配了 approximation的值并从函数中返回,但返回时的值与 approximation的值相同。因此,将其删除意味着过早的优化。但是,调用变量 sqrt表示它是真正的平方根,而不是近似值。因此,应将其删除,让我们

double computeSquareRootBabylonian
(double num,
double initialApproximation,
unsigned int iterations)
{
double approximation = initialApproximation;
unsigned int iteration = 1;

for (unsigned int iterationsRemaining = iterations;
iterationsRemaining > 0;
iterationsRemaining--)
{
approximation =(approximation + (num/approximation))/2;
cout << endl
<< "Cycle " << iteration << " Aproximate: " << approximation << endl;

iteration++;
}
return approximation;
}


5.在每次迭代中记录逐次逼近并不是您总是希望平方根函数执行的事情。我们应该添加一个参数,允许调用代码指定是否记录近似值:

double computeSquareRootBabylonian
(double num,
double initialApproximation,
unsigned int iterations,
bool log)
{
double approximation = initialApproximation;
unsigned int iteration = 1;

for (unsigned int iterationsRemaining = iterations;
iterationsRemaining > 0;
iterationsRemaining--)
{
approximation =(approximation + (num/approximation))/2;
if (log)
{
cout << endl << "Cycle " << iteration << " Aproximate: " << approximation << endl;
}
iteration++;
}
return approximation;
}


编写主要功能

现在,我们已将该程序的所有组成部分准备就绪。我们只需要改变计划

show a greeting
do {
get number from user
compute the squareroot of that number while logging
show the user the squareroot
ask the user if they want to do another computation
} while the user wants the program to keep running
show a farewell


成为一个完整的程序:

int main(int argc, char *argv[]) 
{
//Do this stuff.
}


首先,我们知道如何开始和结束程序。我们要使用函数 showGreeting()showFarewell()表示问候和告别:

int main(int argc, char *argv[]) 
{
showGreeting();
//do {
//get number from user
//compute the squareroot of that number while logging
//show the user the squareroot
//ask the user if they want to do another computation
//} while the user wants the program to keep running
showFarewell();
}


我们知道我们想要获取用户输入并至少计算一次平方根,并且我们知道可以获取一个 bool,它表示用户是否要使用函数 getRunAgain()计算另一个平方根。我们应该 do用户输入和计算 while getRunAgain()

int main(int argc, char *argv[]) 
{
showGreeting();
do {
//get number from user
//compute the squareroot of that number while logging
//show the user the squareroot
} while(getRunAgain());
showFarewell();
}


我们有一个函数 getInputNumber(),它返回一个 double,代表用户要计算其平方根的数字。我们需要使用两次此 double,一次用作平方根函数 computeSquareRootBabylonian()的参数,一次将输入及其平方根输出给用户。结果,我们将需要一个局部变量:

int main(int argc, char *argv[]) 
{
showGreeting();
do {
double number = getInputNumber();
//compute the squareroot of that number while logging
//show the user the squareroot
} while(getRunAgain());
showFarewell();
}


现在我们的平方根函数 computeSquareRootBabylonian()具有四个参数:


计算平方根的数量
初始近似
迭代次数
是否记录每个逐次逼近


我们将传递 number作为第一个参数。现在,我们可以 hardcode其余参数,使用 1进行初始近似,使用 25进行迭代,使用 true进行是否记录。

由于我们只需要使用一次 computeSquareRootBabylonian()的结果(注销结果时),因此无需使用局部变量就可以摆脱困境。为了清楚起见,让我们继续使用以下一种方法:

int main(int argc, char *argv[]) 
{
showGreeting();
do {
double number = getInputNumber();
double squareRoot = computeSquareRootBabylonian(number, 1.0f, 25, true);
//show the user the squareroot
} while(getRunAgain());
showFarewell();
}


我们只需要向用户显示结果:

int main(int argc, char *argv[]) 
{
showGreeting();
do {
double number = getInputNumber();
double squareRoot = computeSquareRootBabylonian(number, 1.0f, 25, true);
cout << endl
<< "The square root of " << num << " is " << sqrt << "!" << endl
<< endl;
} while(getRunAgain());
showFarewell();
}


该程序遗漏了一点:配置 cout的精度。

int main(int argc, char *argv[]) 
{
cout.precision(50);
showGreeting();
do {
double number = getInputNumber();
double squareRoot = computeSquareRootBabylonian(number, 1.0f, 25, true);
cout << endl
<< "The square root of " << num << " is " << sqrt << "!" << endl
<< endl;
} while(getRunAgain());
showFarewell();
}




恢复问题

您问了几个有关 cout的问题:


  在此代码中(第一个 main函数),我将小数的精度特别设置为15。但是,它输出的数字为12个小数。但是在此代码[第二个 main函数]中,它以15位小数输出。 [...]我很困惑为什么会这样。我尝试了cout <<固定<< showpoint;但是当num无缘无故地输出15个零时,它看起来不愉快。谁能启发我为什么会这样以及如何解决?
  
  为什么我不能超过15位小数?如果将精度设置为30/40,即使对我的计算机计算器来说,精度也变为30/40,但对我的输出没有任何作用。我应该使用另一个整数类型而不是double吗?


我将在稍后解决这些问题。首先,我将描述我本人将如何问他们,以便在StackOverflow上获得更好,更快的响应。

要点是发布 short, self-contained, correct (compilable), example。那到底是什么问题呢?它与将 inserting(使用 operator <<)转换为 std::cout(通常转换为 std::ostream)有关。它与使用 double格式化 std::ostream::precision输出有关。在将问题减少到这一点之后,我将开始查看相关文档,如果没有提供足够的解释,请使用这些关键字在StackOverflow上进行搜索。如果找不到解决方案,我将生成一个 example来说明我遇到的困难。

提出第一个问题

第一个问题是,当我们将cout的精度设置为15时,我们只能得到12位小数。让我们编写一个程序,该程序将 double初始化为一个值,将 cout的精度设置为 15并将我们的 double插入到 cout中:

#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
double value = 1.1111111111111111111111111f;
cout.precision(15);
cout << value << endl;
return 0;
}


该程序打印出来

1.11111111111111


小数点后该数字只有14 1。尽管这不是我们所希望的(小数点后是14位而不是12位),但看起来我们走在正确的轨道上。看起来正在发生某种舍入行为。也许我们应该将零放在小数点后的第13位和第14位:

#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
double value = 1.1111111111110011111111111f;
cout.precision(15);
cout << value << endl;
return 0;
}


该程序的输出

1.111111111111


正如我们希望的那样,只有12位数字。因此,我们现在有一个简短的,独立的,正确的(可编译的)示例来提出我们的问题。

陈述第一个问题


  我正在使用 std::cout输出 double。我想显示小数点后的前15位数字,或者至少显示非零数字。但是以这段代码为例


int main(int argc, char *argv[]) 
{
double value = 1.1111111111110011111111111f;
cout.precision(15);
cout << value << endl;
return 0;
}



  输出是 1.111111111111而不是我期望的 1.111111111111001。我可以使用 std::fixed解决此问题


int main(int argc, char *argv[]) 
{
double value = 1.1111111111110011111111111f;
cout.precision(15);
cout << std::fixed << value << endl;
return 0;
}



  不会按预期输出 1.111111111111001。不幸的是,即使所有数字均为零,使用 std::fixed也会始终在小数点后打印15位数字。例如来自的输出


int main(int argc, char *argv[]) 
{
double value = 1.0f;
cout.precision(15);
cout << std::fixed << value << endl;
return 0;
}



  是 1.000000000000000而不是我希望的 1
  
  当其余所有数字均为零时,如何使用 cout输出最多15个十进制数字和更少的十进制数字?


提出第二个问题

第二个问题是,无论我们将 cout的精度设置为高于15多少,我们的输出中都只会获得15个十进制数字。让我们编写一个程序,该程序将 double初始化为一个值,将 cout的精度设置为 30并将我们的 double插入到 cout中:

int main(int argc, char *argv[]) 
{
double value = 1.55f;
cout.precision(30);
cout << value << endl;
return 0;
}


这将输出 1.5499999523162841796875,该数字由小数点后的22位数字组成。这表明我们很不幸运地获得了准确的15位输出:我们遇到第一个问题时遇到的同种舍入行为显然是与平方根函数返回的值的输出进行交互,使得在这种舍入行为下,小数点后第十五位被打印。



回答问题

您想在 double中插入一个 cout,以便显示尽可能多的非零十进制数字,最多15个。 doublecout的字符串表示形式应至少满足以下测试:

 x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxf ----> "x.xxxxxxxxxxxxxxx"
x.xxxxx0000000000000000000000000f ----> "x.xxxxx"
x.000000000000000000000000000000f ----> "x"
x.00000000000000x000000000000000f ----> "x.00000000000000x"


使用 std::ostream::precision不能以任何明显的方式实现。正如您所指出的,我们不能使用 std::fixed,因为这肯定会使上面的第三项测试失败。我们也不能轻易使用默认值,因为如 cplusplus.com所述,


  在默认的浮点表示法上,precision字段指定在总计小数点之前和之后的小数之后要显示的有意义数字的最大数量。


这意味着我们需要考虑小数点前的位数。如果小数点前有3位数字,我们需要使用15 + 3的精度,依此类推。

实现此目的的一种方法是使用 double并返回 std::string的函数:

std::string stringFromDouble(double value, unsigned int decimalDigits)
{
int integerComponent = abs((value > 0) ? (int)(floor(value)) : (int)(ceil(value)));
std::ostringstream integerStream;
integerStream << integerComponent;
std::string integerString = integerStream.str();
unsigned int integerLength = integerString.length();

std::ostringstream stream;
stream.precision(decimalDigits + integerLength);
stream << value;
std::string str = stream.str();
return str;
}

关于c++ - 设置精度无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14290662/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com