Rounding numbers with Java’s NumberFormat...
Take a look at the following numbers and round them to the nearest whole number:
- 2
- 2.1
- 2.2
- 2.3
- 2.4
- 2.49
- 2.5
- 2.51
- 2.6
- 2.7
- 2.8
- 2.9
- 3
I’m pretty confident that you will get the same answers as my 4th grader, which is that the numbers from 1-6 result in a 2 and 7 onwards results in 3, right? Well, given the following code though, you’d be surprised:
- import java.text.DecimalFormat;
- import java.text.NumberFormat;
- public class test {
- public static void main( String [] args ) {
- double [] values = new double[] { 2, 2.1, 2.2, 2.3, 2.4, 2.49, 2.5, 2.51, 2.6, 2.7, 2.8, 2.9, 3.0 };
- final NumberFormat format = new DecimalFormat( "#" );
- for ( double d : values ) {
- System.out.println( d + ": " + format.format( d ) );
- }
- }
- }
Your surprise would come from the fact that the 2.5 rounds down to 2. Why? Well, reading the DecimalFormat javadocs closely, you will notice that the default rounding policy is HALF_EVEN, in which the above behaviour is explained. To change that, simply use format.setRoundingMode( RoundingMode.HALF_UP ); or one of the other policies available in the rounding mode.
Why this is the default behaviour is puzzling to me, but I’ll just add it to the list, which includes the Math.abs() handling of Integer.MIN_VALUE and non-thread-safe SimpleDateFormat (which, for the record, I do not believe that the code suggested in that blog post is guaranteed to be thread-safe either... since the DateFormat class is declared to be non-threadsafe also).
Internet Explorer 8 Compatibility Mode...
Earlier today, myscenicdrives.com released our road trip planner which I am really excited about. There are several more features that I want to build into it, but this was a really nice time to release it and get some feedback from real users.
For the last week, we have been doing some usability testing, optimizations, cross browser testing, and polishing it all up before the press release earlier today. With the final push going out the door late last night, we did our final round of testing and under Internet Explorer 8, I got that dreaded, “A problem displaying [site] caused internet explorer to refresh the webpage using compatibility view.” This resulted in a huge effort to figure out where that message from coming from.
The majority of the testing was done in the latest version of all browsers, which I was really pleasantly surprised at how standards compliant Internet Explorer 9 is. While I had to do a few tweaks specifically for it, it was relatively easy and no more than what I had to do for other browsers. When I cracked up Internet Explorer 8 (via Microsoft’s virtual machine image), it required a lot more tweaks but in the end, it seemed good.
This is why I was really surprised when I loaded up the page last night and saw the compatibility view message. Unfortunately, that message does not provide any insight into what the problem might be. The Microsoft documentation on the matter states that your pages must have a DOCTYPE and validate, but they also hint that there are other undocumented reasons — this makes finding the root of the problem orders of magnitude more frustrating.
After changing things I thought might be suspect, endless googles for any hints, and etc., I started commenting out various chunks of code trying to make it go. At the end, I had a simple empty page with nothing between the opening body tag and the closing body tag, and it was still happening! But this was illuminating because right above where the body tag came out was one little optimization we had done recently.
When usability testing, we noticed that there was a lag in images being displayed which was not user-friendly. To help prevent that problem, we looked into image prefetching techniques, and fell upon the CSS technique:
- body:after {
- content:url(image.png);
- display:none;
- }
This made a world of a difference in testing. According to my research, this technique is suppose to be ignored by browsers that do not support the :after clause and so it felt safe. Since the images in question were very specific to the application being developed and the page in question is not intended to be read by search engines, we decided to inline this code on the page.
Could this be the cause? Well, in trying to narrow it down further, I did comment out the entire style-tag and sure enough, my page did not go into compatibility mode.
This fixed my compatibility-mode problem and hopefully it may help someone else out there.
Math.abs has an edge case...
Consider the following Java code:
- int ai = Math.abs( i );
- assert ai >= 0;
Will the assert ever fire?
Yes, it turns out that it can fire if i = Integer.MIN_VALUE, and you have been warned about this in the Math.abs javadoc, which states “Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.’
Keep this in mind when looking at such innocent looking code...
Java Mail: Make sure the mail.smtp.auth property's value is a String...
If you are using the JavaMail API to send out e-mail via an e-mail server that requires authentication and are getting an error like com.sun.mail.smtp.SMTPSendFailedException: 550 You must authenticate, make sure the mail.smtp.auth property is assigned as a String, like this:
- properties.put( "mail.smtp.auth", "true" );
Not exactly the most obvious bug to find...
Using Ant with Cygwin
If you have ever tried building something with ant under Cygwin, you probably have noticed an error such as the following:
build.xml:35: c:\cygdrive\c\Progra~1\java/SunAppServer\jdk\lib\J2EE.jar
The current Ant documentation suggests that you should change your build.xml to wrap all such environment labels and class paths with code that executes cygpath, but this turns out to create some ugly code, especially if your build scripts use a lot of environment labels.
An alternative scheme that I have just come up with is to use a layer of indication. You can create an ant shell script that translates all of your necessary Cygwin environment labels using cygpath, and then call the ant.bat to do the actual build. The advantage of this approach is that more build.xml files are cross-platform out of the box and require very few, if any, tweaks.
The following file is an example of my approach:
#!/bin/sh
# OS-Specific Stuff
export PATH=`/usr/bin/cygpath --path --windows $PATH`
export TEMP=`/usr/bin/cygpath --path --windows $TEMP`
export TMP=`/usr/bin/cygpath --path --windows $TMP`
# Java Specific Stuff
export JAVA_HOME=`/usr/bin/cygpath --windows $JAVA_HOME`
export J2EE_HOME=`/usr/bin/cygpath --windows $J2EE_HOME`
export TOMCAT_HOME=`/usr/bin/cygpath --path --windows $TOMCAT_HOME`
export CLASSPATH=`/usr/bin/cygpath --path --windows $CLASSPATH`
# Ant Specific Stuff
ORIGINAL_ANT_HOME=$ANT_HOME
export ANT_HOME=`/usr/bin/cygpath --path --windows $ANT_HOME`
# Project-Specific Stuff
export WHATEVER_YOU_NEED=`/usr/bin/cygpath --windows $WHATEVER_YOU_NEED`
# Invoke the ANT.BAT via the original ANT_HOME value
$ORIGINAL_ANT_HOME/bin/ant.bat $1 $2 $3 $4 $5 $6 $7 $8 $9
Of course, this technique can be generally applied to other applications that use environment labels. Hope that helps.
Earlier Entries
- Searching for nil in all the wrong places...
- Clearing an empty java.util.HashMap...
- .NET and loading assemblies for other platforms...
- C++ and finally
- Adapting for Concurrency...
- java.util.concurrent Memory Leaks...
- Strings in C++...
- Of Hacks and Keyboards...
- Commonalities between Home Depot and .NET
- Leonardo’s Laptop...