I was asked the following question and I didn't know how to answer it. I was wondering if anybody could help:
Using C#, and not using any Math functions (Round() and Truncate() aren't allowed) take the following double 3.009784654 and round it to 4 decimal places.
This was for an interview, not for a class project or homework. The interviewer seemed to be trying to get me to use mod, but I still couldn't think of how to do it.
Thanks!
To truncate (since rounding rules were not specified): multiply by 1e4, cast to int, divide by 1e4.
This is a bad interview question, because the task is generally impossible, given the expected tools, because most of the correct results cannot be represented. That is, the common floating-point type cannot represent the correct mathematical result, 3.0098, exactly. So it is impossible to calculate and return the correct answer. You would have to use some alternate mechanism, such as returning the value in a different type (scaled to an integer, in a string, in a decimal floating-point format, et cetera).
I suspect an answer the interviewer may have been expecting is to evaluate (int)(x*10000+.5)*.0001. This scales the value so that the desired results are integers (the rounding quantum, .0001, is scaled to 1), adds .5, truncates to an integer, and reverses the scaling. The combination of adding .5 and truncating is nearly equivalent to rounding, except it requires x to be positive, rounds ties away from zero, and has range/domain issues. Adjustments for those can be made depending on the situation and desired behavior. And, of course, the answers are generally slightly incorrect, due to the inability to represent exact results.
A more interesting answer is to evaluate (x*10000+0x1p52-0x1p52)*.0001. This scales the value, rounds it to an integer, using the current floating-point rounding mode, and undoes the scaling. The rounding is effected because the common double type has 53 bits in its significand, so, when the high bit has value 0x1p52 (252), the low bit’s value is 0x1p0 (20, also known as 1). In order to produce the result of adding 0x1p52, the significand must be rounded, which is done automatically in the floating-point hardware. Then subtracting 0x1p52 removes the added number, leaving the rounded value. As before, there are caveats with range/domain and ensuring the compiler does double-precision arithmetic and not something more, and adjustments can be made. However, it is faster on some hardware than converting to integer and back.
Using fmod or string conversions has worse performance because they require division, which is slow on most common processors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With