这些步进回合是否等效

Are these step-rounds equivalents?

本文关键字:是否 步进      更新时间:2023-10-16

这是我的代码:

#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 位数字),使用可以表示它的最接近的双精度值(我分配给steppedValue的那个)。

例如,取inputValue = 13.55121341223423457并使用 0.1 步长,该值是13.6的(由于浮点数学,这实际上是13.60000000000000142的;但这不是重点,重点是它在概念上返回 .6)。

后来,我采用相同的inputValue并使用vsnprintf功能打印出来,再次考虑0.1的步骤。哪个打印正确13.6.

我的

问题是:在使用我的步长函数或vsnprintf之间,是否存在任何四舍五入到不同步进值的inputValue?即这两个结果是否可以由我的步长函数产生,并且vsnprintf不一致,例如计算/打印不同步进的值?

不,它们不等同。 因为您要除以 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;将解决我提供的示例值的问题。