2

I've been testing this for about an hour and I don't understand what's going on.

In imageJ, if I say:

i = 3.5;
print(round(i));

I get 4.

However, If I say:

      print(65535/(27037-4777)*(26295-4777));
print(round(65535/(27037-4777)*(26295-4777)));

For some reason, I am getting:

63350.5
63350

Shouldnt it be rounding up to 63351?

Ogen
  • 6,499
  • 7
  • 58
  • 124
  • I wasn't aware that `ImageJ` had a `round` function. Have you tried doing the same using the Java API instead (i.e. `Math.round()`) to see what you get? Also, I have a hunch. Try changing `65535` to `65535.0` and see what you get. – rayryeng Jun 07 '14 at 05:46
  • @rayryeng I think you're onto something, I tried it in eclipse and I am getting `63350.49999999999` so it is rounding down to 63350. – Ogen Jun 07 '14 at 05:51
  • AHA... there we go. If you want to avoid instances like that, consider adding a small value to the number that is large enough to bump the number over 63350.5, but small enough that it won't impact any results. Take a look at `java.lang.Math.ulp` – rayryeng Jun 07 '14 at 05:55
  • @rayryeng Now I'm doing it on my casio calculator and its giving me 63350.5 so I have no clue what exactly is going on now... – Ogen Jun 07 '14 at 05:55
  • Try doing this: `double num = 65535/(27037-4777)*(26295-4777); double num2 = Math.round(num + Math.ulp(num)); System.out.println(num); System.out.println(num2);` – rayryeng Jun 07 '14 at 05:56
  • Also, try changing the **order** of the operations. That could also affect the floating point arithmetic. i.e. `print(round(65535*(26295-4777)/(27037-4777)));` – rayryeng Jun 07 '14 at 06:01
  • The rounding before hand doesn't make a difference. Also, I don't think imageJ has a `ulp` function. I can't find one. I added 0.00001 to my code and it works though. The only thing I'm scared of now is maybe it only works for this particular example I'm looking at. But I think its good enough – Ogen Jun 07 '14 at 06:07
  • yeah adding a small constant should be sufficient. I thought you'd be able to intermix the calls to the Java API with `ImageJ`. ah well! – rayryeng Jun 07 '14 at 06:15
  • If you post your answer of adding a small amount ill accept it, I never thought of that! – Ogen Jun 07 '14 at 06:26
  • Cool! Thanks! I'll do it now – rayryeng Jun 07 '14 at 06:29

1 Answers1

1

Taking a look at your comments, the number that was generated through that calculation is actually 63350.499999..., and so when you try and round, the number gets rounded down and you get 63350. One thing that I can suggest is to add a small constant that may seem innocuous in hindsight, but it will resolve situations like this. You want to make it small enough so that it'll push the fractional part of your number over to the 0.5 range so it'll round successfully, but it won't interfere how round works for the other fractional parts.

The Java API has a function called Math.ulp that will compute the next possible fractional component that is after a particular floating point number that you specify. However, because ImageJ doesn't have this functionality, consider adding something small like 1e-5. This may seem like a foolish hack, but this will certainly avoid the situation like what you're experiencing now. This constant that you're adding should also not affect how round works in ImageJ.


tl;dr: Add a small constant to your number (like 1e-5) then round. This shouldn't affect how round works overall, and it'll simply push those numbers with a fractional component that are hovering at the 0.5 mark to be truly over 0.5.

Good luck!

rayryeng
  • 102,964
  • 22
  • 184
  • 193