-1

I have a method like

  private static double getMinorVersion(final double minorVersion) {
        return minorVersion + 0.1;
  }

When I test this

   final Version version = new Version(1.3, VersionType.MINOR, 0.0);
   final Version newVersion = versionManager.patch(version);
   assertEquals(1.4, newVersion.getVersionNumber(), delta); // delta = 0.0

I get

java.lang.AssertionError: 
Expected :1.4
Actual   :1.4000000000000001

How can I fix it to return 1.4?

daydreamer
  • 87,243
  • 191
  • 450
  • 722

3 Answers3

7

Do not use doubles to represent software version numbers. They should be stored as strings.

Along with running into precision issues, like you've noticed, version numbers are not decimal numbers. For instance, convention is that the version numbers 1.1 and 1.10 are not equal (instead, 1.10 is the version following 1.9), and version numbers commonly contain multiple periods (e.g, 1.1.1) or non-digit characters (e.g, 1.0b2).

  • another way is to use multiple integers. like major.minor.build and the pieces are integers. this makes it easier to compare one version against another. – thang Feb 11 '13 at 01:53
  • @thang: Still doesn't help you when version numbers include components that aren't integers (like my example, `1.0b2`). –  Feb 11 '13 at 01:57
  • so don't use letters. it makes it more difficult to interpret. for example, linux kernel's style is good. note that windows has a versioning built into the exe, and it only lets you use numbers and periods. – thang Feb 11 '13 at 01:58
  • @thang: It depends a bit on what you're planning to do with this class, I guess. If you're trying to represent version numbers that you didn't come up with yourself, though, you can't make very many assumptions about what they might look like. –  Feb 11 '13 at 01:59
  • there are trade offs that you have to make. if you want totally generic, then you lose out on simple ordering... – thang Feb 11 '13 at 02:00
  • 1
    @thang: There are readily available routines that'll do comparisons on generic version numbers. Debian has one, mentioned in http://stackoverflow.com/questions/4957514/ –  Feb 11 '13 at 03:50
1

You can fix it by explicitly choosing a precision and then rounding. One way to do this could be by temporarily casting to an int like this:

private static double getMinorVersion(final double minorVersion) {
    return ((int) ((minorVersion  + 0.1) * 100)) / 100.0;
}

Using 100, of course, will then give you two digits of precision, like 1.38, but you won't be able to do 1.293 for example.

Aside: Should be obvious, but keep in mind that getMinorVersion(1.9) will give you 2.0, not 1.10 !

Markus A.
  • 12,349
  • 8
  • 52
  • 116
0

1- To safely compare double you need to do something like:

boolean isEqual(double a, double b){
     return a == b ? true : Math.abs(a - b) < 0.000001; // some epsilon 
}

2- As suggested, program version number should be string not double

3- You can implement something similar to android app in which there are two types of version. First, is internal integer version number that always increment with every build and it can be used to compare program version; however this is not visible to the users. Second, is the string version which is a string (i.e major.minor) and is visible to the users

iTech
  • 18,192
  • 4
  • 57
  • 80