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
是不一致的,例如计算/打印不同步骤的值?
答案 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;
将使用我提供的示例值解决问题。