A simple Java puzzler

By Confusion on Thursday 18 June 2009 14:59 - Comments (17)
Categories: Java, Software engineering, Views: 2.895


Java:
1
2
final long YEAR_IN_MS = 1000 * 60 * 60 * 24 * 365;
        System.out.println(YEAR_IN_MS);


What will be printed?

Volgende: Installing DB2 Express C on linux 06-'09 Installing DB2 Express C on linux
Volgende: Undecipherable product descriptions 06-'09 Undecipherable product descriptions

Comments



By Tweakers user remunj, Thursday 18 June 2009 15:02

31536000000 ????

By Tweakers user mr_obb, Thursday 18 June 2009 15:04

Gezien 31536000000 < 2^63 zou ik inderdaad ook gewoon zeggen 31536000000

By Tweakers user Jaap-Jan, Thursday 18 June 2009 15:09

Het wordt geconverteerd naar een 32-bits int, dus je krijgt overflow. :P

By Tweakers user Herko_ter_Horst, Thursday 18 June 2009 15:09

Er staan enkel int literals in de formule, daar gaat het fout. Eén l extra (achter één van de getallen) verhelpt het probleem.

[Comment edited on Thursday 18 June 2009 15:10]


By Tweakers user Rctworld, Thursday 18 June 2009 15:11

1471228928?

final long YEAR_IN_MS = 1000 * 60 * 60 * 24 * 365L;
System.out.println(YEAR_IN_MS);

Levert wel 31536000000 op...

[Comment edited on Thursday 18 June 2009 15:12]


By Tweakers user Jaap-Jan, Thursday 18 June 2009 15:12

@Herko_ter_Horst

Klopt. Alle berekeningen in Java worden standaard op 32 bits gedaan, als de argumenten in een int passen. Als één van de argumenten een long is, wordt er een berekening op 64 bits gedaan. Een 'l' achter één van de argumenten plakken zou al genoeg geweest zijn.

@Rctworld

Dat soort quirks zou je eigenlijk wel moeten kennen, dit is één van de bekendste 'bugs' van Java.

[Comment edited on Thursday 18 June 2009 15:18]


By Tweakers user LinuX-TUX, Thursday 18 June 2009 15:16

Ik ga met Rctworld mee
1471228928

Al hoewel
31536000000
dichter in de buurt van de werkelijkheid komt.

Heb ik nu een ijsje verdient?

[Comment edited on Thursday 18 June 2009 15:17]


By Tweakers user roeleboel, Thursday 18 June 2009 15:18

Bovenstaande code op sun jdk 6.13 win xp 32bit geeft
1471228928
??? waar dat vandaan komt snap ik toch niet goed...
(klasse bevat _geen_ andere code dan de 2 regels hierboven, op de noodzakelijke 'public static void main'-regel & bijhorende haakjes na...

Edit:
@mezelf:
in het vervolg geen kwartier bezig zijn met testen terwijl ge aan het reageren zijt...
Of toch op zijn minst ne refresh doen vooraleer ik mijn reactie effectief plaats :-)

@Confusion:
Toen ik begon te reageren stonden er nog maar 2 commentaren... en met de ondertussen bijgevoegde te lezen snapte ik ook dat het over een overflow ging...

[Comment edited on Thursday 18 June 2009 15:42]


By Tweakers user Confusion, Thursday 18 June 2009 15:34

* Confusion geeft LinuX-TUX een virtueel ijsje

De belangrijkste les die ik hier van geleerd heb is: zoek ook waar het onmogelijk kan liggen. Daardoor vond ik de bug vandaag in 5 minuten, in tegenstelling tot de eerste keer dat ik tegen zoiets aanliep. Niettemin las ik er nog steeds overheen en moest ik YEAR_IN_MS echt printen voordat ik zag dat dat natuurlijk niet kon.

@roeleboel:
de uitkomst van de berekening is een int, die pas na de berekening naar een long wordt geconverteerd. Dan is het kwaad al geschied.

[Comment edited on Thursday 18 June 2009 15:36]


By Tweakers user Nick_S, Thursday 18 June 2009 16:09

Als je dit soort quirks "leuk" vindt om te weten, kan ik het boek Java Puzzlers van Joshua Bloch en Neal Gafter aanraden. Wel de tweede editie nemen, daar komen ook wat Java 5 dingen aan bod. Dat ging over Effective Java, ook een aanrader.

[Comment edited on Thursday 18 June 2009 16:17]


By Tweakers user momania, Thursday 18 June 2009 17:27

Just use proper frameworks for these things... like joda-time:


Java:
1
final long yearInMs = Period.years(1).getMillis();


:P :Y)

By Tweakers user Jory167, Thursday 18 June 2009 17:48

momania, do you really think a "framework" should be used for something like that? Whats next?
code:
1
int hourInSeconds = Period.hours(1).getSeconds();

(Note: I have no idea if your Period class as an hours() function, nor if its result has a getSeconds().) Or even:
code:
1
int minuteInSeconds = Period.minutes(1).getSeconds();



Personally, I would write this:
code:
1
final long YEAR_IN_MS = 31536000000; /*1000 * 60 * 60 * 24 * 365*/

Its the fastest solution, and in my opinion its just as readable as what Confusion used more readable then using that joda-time framework. (Especially for people who don't know the joda-time framework, like me.)

By Tweakers user Nick_S, Thursday 18 June 2009 18:03

Als je / je team toch al bekend is met joda-time, dan zou ik hem zeker ook hier voor gebruiken. Als je veel met datums, tijden en periodes aan de gang gaat, is joda-time zeker een verademing boven het standaard Java datum framework. (Of je nu java.util.Date gebruikt of joda-time, het blijven alle 2 frameworks.)

By Tweakers user Phyxion, Thursday 18 June 2009 19:23

Klein reken sommetje, 32 bit limit kan tot precies 4294967296. De uitkomst zou 31536000000 zijn. Als je kijkt wat er over blijft als je 4294967296 van 31536000000 blijft afhalen:
1471228928
Dat is de uitkomst die Java geeft.
En Java is oh zo geweldig :')

By Tweakers user GrooV, Thursday 18 June 2009 20:57

The operation overflows at compile time in checked mode

Dat zegt Visual Studio :Y)

By Tweakers user Snake, Thursday 18 June 2009 22:50

@Jory167: Wat maakt het uit als je het neerschrijft? Gewoon de berekening noteren, die wordt toch gecompileerd :)

@GrooV: VS.NET FTW =)

@Jaap-Jan: Niet ALLE berekeningen. Een getal gewoon (zonder komma, passent in een int) wordt geinterpreteerd als een int.

[Comment edited on Thursday 18 June 2009 22:52]


Comments are closed