Home > Software engineering >  Function to round a float to nearest float with specific allowed decimals
Function to round a float to nearest float with specific allowed decimals

Time:01-24

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
  •  Tags:  
  • Related