The techniques mentioned below use eps
and fix
. These might be less "uglier" than rounding
for your case. Let's look at these step by step with some codes and comments.
%%// Original indices
org_indices = [15 30 45 60]
%%// Scaled indices
scaled_indices = org_indices/3165
%%// Retrieved indices that are yet to be converted to exact integers
retrieved_indices = scaled_indices*3165
%%// Verify precision issue
check_ind1 = retrieved_indices(1) - 15
check_ind1
outputs 1.7764e-15
and is not exactly zero.
We can use eps that according to the official MATLAB documentation says - If d = eps(X), then d is the positive distance from abs(X) to the next larger in magnitude floating point number of the same precision as X.
Thus, we can calculate such distances/offsets as follows -
eps_val = eps(retrieved_indices)
eps_val
could be thought of as window vector that determines within which if an element lies, must correspond to the integer that also lies within it. To make it easy for us, we can use the maximum of these window values for our decision making and to make it very safe, we can increase this width 10 times and let's call it max_window_width -
max_window_width = 10*max(eps_val)
This is not as ugly as rounding because rounding uses a window length of 1
because of its range [-0.5 0.5]
, whereas this one uses a window length of 7.1054e-14
.
Finally, we can get the original indices back by adding this maximum width and then truncating the decimal portion using fix
-
retrieved_indices2 = fix(retrieved_indices + max_window_width)
One can check back the values for exactness -
check_ind2 = retrieved_indices2(1) - 15
check_ind2
outputs 0
.