在不使用流的情况下设置双精度 (ios_base::precision)

Posted

技术标签:

【中文标题】在不使用流的情况下设置双精度 (ios_base::precision)【英文标题】:Setting the precision of a double without using stream (ios_base::precision) 【发布时间】:2012-09-10 09:58:49 【问题描述】:

有没有办法在不使用流的情况下做到这一点?例如,像这样:

double a = 6.352356663353535;
double b = a.precision(5);

代替:

double a = 6.352356663353535;
std::cout.precision(5);
std::cout << a << std::endl;

我是 C++ 新手,我很好奇。提前谢谢。

【问题讨论】:

为了澄清,我假设在第一个示例之后std::cout &lt;&lt; b &lt;&lt; std::endl; 应该产生与第二个示例相同的输出? 不,对于第一个示例,双 b 可以将 a 减少到 5 sig。 fig,而在第二个示例中,不需要该变量。 这就是我询问输出的原因。显然,您对内部表示感到困惑,所以我想知道您希望在外部看到什么。 是的,我想得到一个 5.s.f 的数字。我现在想知道是否可以从流中获取字符串,如果可以,如何使用第二个示例来实现。 【参考方案1】:

我已根据@john、@Konrad 和@KennyTM 的建议修改了代码。我已经检查过它是否适用于负数。

#include <cmath>
#include <cstdio>
using namespace std;
int main()

   double a = 6.352356663353535;
   double  intpart;
   double fractpart = modf (a, &intpart);
   fractpart  = roundf(fractpart * 100000.0)/100000.0; // Round to 5 decimal places
   double b = intpart + fractpart;
   printf("%.5lf", b);

输出

6.35236

【讨论】:

您应该使用函数floor 而不是可能溢出的长转换。 double b = floor(a*10000.0)/10000.0;(可能使用 ceil 表示 -ve 数字)。 问题是关于 C++ 的:请不要在你的回答中使用旧版标头。 @KonradRudolph 我对所有这些术语都不熟悉,抱歉;什么是“旧版标头”? @DereckKachere:应该使用 cmath 和 cstdio 而不是 math.h 和 stdio.h。 @ÖöTiib 从 C 的角度来看,这不是遗留问题,但我们在这里讨论的是 C++,它在哪里,请参阅 C.2。 (“在 C++ 中不推荐使用它们”)。此外,&lt;math.h&gt;确实提供了 C++ (D.5) 中的重载。【参考方案2】:

doubles 几乎普遍实现为IEEE floating point numbers。它们的精度仅取决于数字大小(在 double 的情况下,它是“double-precision floating point number”的缩写,它是 53 位)。无法手动设置浮点数的精度。

显示精度始终是输出格式的属性,而不是数字的属性。不要试图通过四舍五入来改变数字,这样的操作是没有意义的。您不需要降低数字的精度,除非是出于显示目的。

【讨论】:

IEEE-754 很常见,但不是必需的。 @MSalters 但明确这一点会使答案更加复杂,但不会增加显着价值。不过,我添加了一个小警告。 嗯,有真正的 IBM 机器具有十进制浮点硬件。实际上,您可以将尾数中的一些尾随数字归零。 @KonradRudolph 你能看看这个问题并提供你的意见吗?万分感谢***.com/questions/44999495/…【参考方案3】:

无论您做什么,double 始终具有相同的内部精度(很可能是 53 位二进制精度)。只有在以十进制形式写出双精度文本时,您才能控制输出的十进制精度。所以不,您不能将二进制双精度数的精度设置为除本机精度之外的任何其他值(不包括十进制精度)。

如果您想要的只是将一个数字四舍五入到给定的小数位数,那么请查阅 Phillip 的答案(但要加上 john当然,康拉德是用他们的 cmets 制造的)。但请注意,这不会改变基础类型的精度,并且所有使用此数字的计算都将以二进制双精度执行。此外,这种四舍五入的十进制数不需要在底层二进制浮点类型中精确表示。

如果您真的想执行精确的十进制运算,那么您必须寻找提供实际十进制浮点类型的第三方库。

【讨论】:

好的。感谢你们所有人:John、@phillip 和 Christian。现在更有意义了。【参考方案4】:

使用此功能,但首先需要将数字转换为wstring

INPUT L"6.4400"
std::wstring round(std::wstring text) 
    int64_t length = text.length() - 1;
    for (int64_t i = length; i >= 0; i--) 
        if (text[i] != L'0') 
            if (text[i] == L'.') 
                text.replace(i, 1, L"");
                break;
            
            break;
        
        text.replace(i, 1, L"");
    
    return text;

OUTPUT L"6.44"

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于在不使用流的情况下设置双精度 (ios_base::precision)的主要内容,如果未能解决你的问题,请参考以下文章

如何在不丢失 swift 精度的情况下将 String 转换为 Double [重复]

在 .net 中,如何在十进制和双精度之间进行选择

在 .net 中,如何在十进制和双精度之间进行选择

c 改变双精度数的指数

在不关闭底层流的情况下安全地使用带有 HttpContent.ReadAsStreamAsync() 的 StreamReader

将 Haversine 结果作为双精度类型添加到数据集