这些步骤是等效的吗?

时间:2017-10-30 13:44:46

标签: c++ rounding

This是我的代码:

#include <iostream>
#include <limits>
#include <math.h>
#include <stdio.h>

typedef std::numeric_limits< double > dbl;

double StepValue(double value) {
    return floor(0.5 + value / 0.1) * 0.1;
}

void PrintValue(int maxlen, const char *fmt, ...) 
{
    char buffer[20];
    va_list arglist;
    va_start(arglist, fmt);
    vsnprintf(buffer, maxlen, fmt, arglist);
    va_end(arglist);

    std::cout << "p: " << buffer << std::endl;
}

int main()
{
    std::cout.precision(dbl::max_digits10);
    std::cout << std::fixed;

    double inputValue = 13.55121341223423457;
    std::cout << "v: " << inputValue << std::endl;

    double steppedValue = StepValue(inputValue);
    std::cout << "f: " << steppedValue << std::endl;   

    PrintValue(20, "%.1f", inputValue);
}

基本上,我接受inputValue并将其四舍五入到我需要的最接近的步长值(逗号后面的1位数),使用可以表示它的最近的双精度值(我分配给{{{ 1}})。

例如,取steppedValue并使用inputValue = 13.55121341223423457步,值为0.1(由于浮点数学而实际为13.6;但是这不是重点,重点是从概念上回归.6。

稍后,我使用相同的13.60000000000000142并使用inputValue函数进行打印,再次考虑vsnprintf的步骤。哪个打印正确0.1

我的问题是:在使用我的步骤函数或13.6之间可以存在任何inputValue,它可以舍入到不同的步进值吗?即两个结果可以来自我的步进函数而vsnprintf是不一致的,例如计算/打印不同步骤的值?

1 个答案:

答案 0 :(得分:1)

不,他们不相同。因为你除以0.1(不能精确表示),而不是乘以10(可以),所以有一个非常接近中点的数字,其中舍入将朝不同的方向发展。这可能取决于编译器和执行环境。使用Visual Studio 2015,使用

编译为32位程序
double inputValue = std::nextafter(0.05, 0.0);

给出

的值
f: 0.10000000000000001
p: 0.0

在舍入中乘以10可能会解决问题,但这取决于vsnprintf如何处理舍入。

StepValue更改为return std::round(value * 10.0) / 10.0;将使用我提供的示例值解决问题。