A simple Java puzzler
Java:
1 | final long YEAR_IN_MS = 1000 * 60 * 60 * 24 * 365;
|
What will be printed?
|
|
Installing DB2 Express C on linux |
|
|
Undecipherable product descriptions |
Comments
3.1536E10 
31536000000 ????
Gezien 31536000000 < 2^63 zou ik inderdaad ook gewoon zeggen 31536000000
Het wordt geconverteerd naar een 32-bits int, dus je krijgt overflow. 
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]
1471228928?
final long YEAR_IN_MS = 1000 * 60 * 60 * 24 * 365L;
System.out.println(YEAR_IN_MS);
Levert wel 31536000000 op...
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]
@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.
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]
Ik ga met Rctworld mee
1471228928
Al hoewel
31536000000
dichter in de buurt van de werkelijkheid komt.
Heb ik nu een ijsje verdient?
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]
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...
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]
* 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.
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]
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]
Just use proper frameworks for these things... like joda-time:
Java:

Java:
1 | final long yearInMs = Period.years(1).getMillis(); |
momania, do you really think a "framework" should be used for something like that? Whats next?
code:
(Note: I have no idea if your Period class as an hours() function, nor if its result has a getSeconds().) Or even:
code:
Personally, I would write this:
code:
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.)
code:
1
| int hourInSeconds = Period.hours(1).getSeconds(); |
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*/ |
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.)
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
1471228928
Dat is de uitkomst die Java geeft.
En Java is oh zo geweldig
The operation overflows at compile time in checked mode
Dat zegt Visual Studio
Dat zegt Visual Studio
@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.
@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]