12. nov. 2009

DecimalFormat and rounding off

Why does DecimalFormat round off wrong?


I have this nice method that can format a double.
You may also specify the number of decimals.

public static String formatNumber(double number, int decimals) {
String pattern = "###,##0";
if (decimals > 0) {
pattern += "." ;
// Add the wanted number of decimals to the pattern
for (int i = 0; i < decimals; i++) {
pattern += "0";
}
}

// Get the English version of the decimalformatter
DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(
Locale.ENGLISH);
df.applyPattern(pattern);

return df.format(number);
}


Now I want to run it:

public static void main(String[] args) {
testNumber(1.5, 0, "2");
testNumber(2.5, 0, "3");
testNumber(2.15, 1, "2.2");
testNumber(2.25, 1, "2.3");
}
public static void testNumber(double number, int decimals,
String expected) {
String formatted = formatNumber(number, decimals);
System.out.print("Testing " + number + ", decimals " +
decimals + ", Actual = " + formatted);
if (formatted.equals(expected)) {
System.out.println(" Expected = " + expected);
} else {
System.out.println(" Expected = " + expected +
" <- Not the same!");
}
}


The outcome is:

Testing 1.5, decimals 0, Actual = 2 Expected = 2
Testing 2.5, decimals 0, Actual = 2 Expected = 3 <- Not the same!
Testing 2.15, decimals 1, Actual = 2.2 Expected = 2.2
Testing 2.25, decimals 1, Actual = 2.2 Expected = 2.3 <- Not the same!


What???
It looks like it rounds off completely randomly.
If you look closer to the documentation, you'll find that DecimalFormat uses ROUND_HALF_EVEN.
This means that "Rounding mode to round towards the 'nearest neighbor' unless both neighbors are equidistant, in which case, round towards the even neighbor. "

But I don't want that, I want it to round up where the fraction is >= 0.5, which is ROUND_HALF_UP, but it seems that you can't change the way DecimalFormat is rounding off, so I've found a way to do it.

If you move the fraction, so the rounding off allways is at the first decimal, you can use Math.round which uses ROUND_HALF_UP, and then set back the correct position for the fraction.

Something like:

double pow = Math.pow(10, decimals);
double numberPowed = number * pow;
number = Math.round(numberPowed) / pow;


Now we can format it using DecimalFormat

But we're not yet homefree, because Math.round is returning a Long, which can't hold big numbers like doubles, so we can only do this trick if the number don't get too big!

The complete method now looks like this:

public static String formatNumber(double number, int decimals) {
double pow = Math.pow(10, decimals);
double numberPowed = number * pow;
// Only do it if the number is not too big
// Math.round returns the neastest Long, so it must fit
// inside a long
if (numberPowed < Long.MAX_VALUE) {
number = Math.round(numberPowed) / pow;
}

String pattern = "###,##0";
if (decimals > 0) {
pattern += "." ;
// Add the wanted number of decimals to the pattern
for (int i = 0; i < decimals; i++) {
pattern += "0";
}
}

// Get the English version of the decimalformatter
DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(
Locale.ENGLISH);
df.applyPattern(pattern);

return df.format(number);
}


And we'll get the right outcome:

Testing 1.5, decimals 0, Actual = 2 Expected = 2
Testing 2.5, decimals 0, Actual = 3 Expected = 3
Testing 2.15, decimals 1, Actual = 2.2 Expected = 2.2
Testing 2.25, decimals 1, Actual = 2.3 Expected = 2.3

14. aug. 2009

Two convicted in U.K. for refusal to decrypt data

Two convicted in U.K. for refusal to decrypt data

What will come next?
That you must reveal your banking password?

It seems that the authorities want to look in your diary.

I think it should not be possible to force people to reveal such stuff.

It's fine, that the authorities can get a court-order to see your financial transactions.

27. apr. 2009

28. feb. 2009

Set the default printer using command shell

I want to set my default printer using a command shell, can it be done?


Yes...

Running "RUNDLL32 PRINTUI.DLL,PrintUIEntry /?" gives you a list of what you can do, and this help you set the default printer:
RUNDLL32 PRINTUI.DLL,PrintUIEntry /y /n "hp psc 1200 series"

See: Usage and examples

26. feb. 2009

Pragtfuldt 1-plans rækkehus med god beliggenhed i Ishøj



Pragtfuldt 1-plans rækkehus med god beliggenhed i Ishøj
Den perfekte bolig hvad enten man er ung eller gammel!


Står du og mangler et rækkehus i Ishøj eller kender du nogen der gør, så er dette rækkehus perfekt...

BEMÆRK:
Åbent hus søndag d. 01.03.2009 kl. 13.00 - 13.30,
Bøgelunden 57
2635 Ishøj


Se flere billeder og yderligere oplysninger: Danbolig