将浮点数舍入到具有特定允许小数的最接近浮点数的函数
Function to round a float to nearest float with specific allowed decimals
我正在尝试编写一个如下所示的函数(C++,但接受任何语言的答案)
float roundToGivenDecimals(float input, float allowedDecimals[])
用法:
float roundToGivenDecimals(10.4, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 10.45
float roundToGivenDecimals(3.15, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 3.15
float roundToGivenDecimals(3.01, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 2.99
类似于标准的 round() 方法,但只允许使用特定的小数值
我已经考虑了一段时间,但我正在努力想出一个好的解决方案,任何想法将不胜感激!
根据@High Performance Marks 的建议,我创建了以下内容:
float roundToGivenDecimals(float input, float allowedDecimals[], int numAllowedDecimals) {
double inputIntegral;
double inputFractional;
inputFractional = modf(input, &inputIntegral);
float minAbsValue;
int minAbsValueIndex;
for(int i = 0; i < numAllowedDecimals; i++) {
float allowedDecimalMinusFractional = allowedDecimals[i] - inputFractional;
float absVal = abs(allowedDecimalMinusFractional);
if (absVal < minAbsValue || i == 0) {
minAbsValue = absVal;
minAbsValueIndex = i;
}
}
return inputIntegral + allowedDecimals[minAbsValueIndex];
}
这大部分是正确的并且适用于我的目的,但在某些情况下此功能不会按预期运行:
float roundToGivenDecimals(10.4, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 10.45 correct
float roundToGivenDecimals(3.15, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 3.15 correct
float roundToGivenDecimals(3.01, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 3.1 <-- this is incorrect, the expected output should be 2.99
@Daniel Davies,我稍微修改了你的答案,现在它可以正常工作了:
double roundToGivenDecimals(double input, double allowedDecimals[], int numAllowedDecimals) {
double inputFractional = input - floor(input);
double result = input;
double minDiff = 1;
for (int i = 0; i < numAllowedDecimals; ++i) {
if (fabs(inputFractional - allowedDecimals[i]) < minDiff) {
result = floor(input) + allowedDecimals[i];
} else if (fabs(inputFractional + 1 - allowedDecimals[i]) < minDiff) {
result = floor(input) - 1 + allowedDecimals[i];
}
minDiff = fabs(input - result);
}
return result;
}
我正在尝试编写一个如下所示的函数(C++,但接受任何语言的答案)
float roundToGivenDecimals(float input, float allowedDecimals[])
用法:
float roundToGivenDecimals(10.4, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 10.45
float roundToGivenDecimals(3.15, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 3.15
float roundToGivenDecimals(3.01, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 2.99
类似于标准的 round() 方法,但只允许使用特定的小数值
我已经考虑了一段时间,但我正在努力想出一个好的解决方案,任何想法将不胜感激!
根据@High Performance Marks 的建议,我创建了以下内容:
float roundToGivenDecimals(float input, float allowedDecimals[], int numAllowedDecimals) {
double inputIntegral;
double inputFractional;
inputFractional = modf(input, &inputIntegral);
float minAbsValue;
int minAbsValueIndex;
for(int i = 0; i < numAllowedDecimals; i++) {
float allowedDecimalMinusFractional = allowedDecimals[i] - inputFractional;
float absVal = abs(allowedDecimalMinusFractional);
if (absVal < minAbsValue || i == 0) {
minAbsValue = absVal;
minAbsValueIndex = i;
}
}
return inputIntegral + allowedDecimals[minAbsValueIndex];
}
这大部分是正确的并且适用于我的目的,但在某些情况下此功能不会按预期运行:
float roundToGivenDecimals(10.4, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 10.45 correct
float roundToGivenDecimals(3.15, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 3.15 correct
float roundToGivenDecimals(3.01, [0.1, 0.45, 0.67, 0.80, 0.99]) // output: 3.1 <-- this is incorrect, the expected output should be 2.99
@Daniel Davies,我稍微修改了你的答案,现在它可以正常工作了:
double roundToGivenDecimals(double input, double allowedDecimals[], int numAllowedDecimals) {
double inputFractional = input - floor(input);
double result = input;
double minDiff = 1;
for (int i = 0; i < numAllowedDecimals; ++i) {
if (fabs(inputFractional - allowedDecimals[i]) < minDiff) {
result = floor(input) + allowedDecimals[i];
} else if (fabs(inputFractional + 1 - allowedDecimals[i]) < minDiff) {
result = floor(input) - 1 + allowedDecimals[i];
}
minDiff = fabs(input - result);
}
return result;
}