【问题标题】:C++ printf Rounding?C++ printf 舍入?
【发布时间】:2015-11-02 22:00:44
【问题描述】:

我的代码:

   // Convert SATOSHIS to BITCOIN
    static double SATOSHI2BTC(const uint64_t& value)
    {
        return static_cast<double>(static_cast<double>(value)/static_cast<double>(100000000));
    }

    double dVal = CQuantUtils::SATOSHI2BTC(1033468);
    printf("%f\n", dVal);
  printf("%s\n", std::to_string(dVal).data());

谷歌输出:0.01033468

程序输出:0.010335 对于printfstd::to_string

调试器输出:0.01033468

printfstd::to_string 是否对数字进行四舍五入? 如何获得具有正确值的字符串?

【问题讨论】:

  • to_string() 和(我猜是printf)的默认精度是小数点后 6 位(参见:stackoverflow.com/questions/14520309/…stackoverflow.com/questions/16605967/…
  • “google”(wtf?) 和调试器输出都没有任何意义。
  • 抱歉,复制/粘贴错误。更新。如果您使用 google calc,您会得到 Google 输出。感谢@Nim 的回答
  • 为什么?!只需将其保留为整数 Satoshis。无论您希望通过将其转换为double 来解决什么问题,都可以解决一些其他(更好!)的方法。
  • @DavidSchwartz 我将此作为SATOSHI 供内部使用,但我需要通过提供双精度值将数据呈现给交易所。如果与我所拥有的一起去,那么我将订购比我要求的更多的东西(由于 std::to_string 中的四舍五入)。

标签: c++


【解决方案1】:

字段宽度有点棘手

#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <sstream>
#include <limits>

#define INV_SCALE 100000000

static const int      WIDTH   = std::ceil(
                                    std::log10(std::numeric_limits<uint64_t>::max())
                                ) + 1 /* for the decimal dot */;
static const uint64_t INPUT   = 1033468;
static const double   DIVISOR = double(INV_SCALE);
static const int      PREC    = std::ceil(std::log10(DIVISOR));

static const double   DAVIDS_SAMPLE = 1000000.000033;

namespace {
std::string to_string(double d, int prec) {
    std::stringstream s;
    s << std::fixed
      << std::setw(WIDTH)
      << std::setprecision(prec) 
      << d;
    // find where the width padding ends    
    auto start = s.str().find_first_not_of(" ");
    // and trim it left on return
    return start != std::string::npos ? 
                    &(s.str().c_str()[start]) : "" ;
}
}

int main() {
    for (auto& s : 
            {to_string(INPUT/DIVISOR, PREC), to_string(DAVIDS_SAMPLE, 6)} 
        ) std::cout << s << std::endl;

    return /*EXIT_SUCCESS*/ 0;
}

输出:

0.01033468
1000000.000033

【讨论】:

  • 这太疯狂了...,我想不通。尊重。
  • 只是一个草图;这太昂贵了,不能具有广泛的普遍性。但它应该适合你。
【解决方案2】:

std::to_string 函数使用与 printf 相同的符号:

7,8) 将浮点值转换为内容相同的字符串 正如std::sprintf(buf, "%f", value) 所产生的那样 大缓冲区。

printf 文档显示:

精度指定出现在 小数点字符。默认精度为 6。

您可以使用%.32f 表示您想要多少个小数(例如32):

printf("%.32f\n", dVal);

我找不到使用to_string 更改小数位数的方法,但您可以使用sprintf 将值打印到字符串:

char buffer [100];
sprintf (buffer, "%.32f", dVal);
printf ("%s\n",buffer);

如果你想要std::string:

std::string strVal(buffer);

【讨论】:

    【解决方案3】:

    感谢所有回答,

    这成功了:

    std::stringstream ss;
    ss << std::setprecision(8) << dVal;
    std::string s = ss.str();
    printf("ss: %s\n", s.data());
    

    输出:

    ss:0.01033468

    【讨论】:

    • 这不起作用。尝试使用 1000000.000033 的 dVal。甚至只是this
    • 难以置信.. 那么如何处理呢?
    • 不要使用double。您为什么要为此使用double?这完全没有意义。您想将整数转换为字符串,为什么要使用其他数字类型?这太疯狂了。
    • double 是为了保证 Satoshi 到 BTC 的分割是双精度的。那么这必须表示为字符串,我不明白还有什么其他的选择?
    • 首先,将整数转换为表示该整数的字符串。然后根据需要在字符串中添加前导零。然后在字符串中需要的地方插入一个小数点。
    猜你喜欢
    • 2015-05-23
    • 2016-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    • 2021-11-05
    • 1970-01-01
    相关资源
    最近更新 更多