I'm trying to write a function that behaves like the following (c , but answers in any language accepted)
float roundToGivenDecimals(float input, float allowedDecimals[])
usage:
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
Similar to a standard round() method, but with only specific fractional values allowed
I've been thinking this over for a while but I'm struggling to come up with a nice solution, any ideas would be greatly appreciated!
CodePudding user response:
@Daniel Davies, I changed a bit your answer, now it works correctly:
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;
}
CodePudding user response:
following @High Performance Marks suggestion I have created the following:
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];
}
This is mostly correct and works for my purposes, but there are eventualities where this function does not behave as intended:
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
