Return-Path: Delivered-To: apmail-tomcat-users-archive@www.apache.org Received: (qmail 64621 invoked from network); 19 Jan 2011 03:11:26 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 19 Jan 2011 03:11:26 -0000 Received: (qmail 21519 invoked by uid 500); 19 Jan 2011 03:11:23 -0000 Delivered-To: apmail-tomcat-users-archive@tomcat.apache.org Received: (qmail 21205 invoked by uid 500); 19 Jan 2011 03:11:21 -0000 Mailing-List: contact users-help@tomcat.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Tomcat Users List" Delivered-To: mailing list users@tomcat.apache.org Received: (qmail 21196 invoked by uid 99); 19 Jan 2011 03:11:20 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Jan 2011 03:11:20 +0000 X-ASF-Spam-Status: No, hits=0.7 required=10.0 tests=RCVD_IN_DNSWL_NONE,SPF_NEUTRAL X-Spam-Check-By: apache.org Received-SPF: neutral (nike.apache.org: local policy) Received: from [76.96.62.32] (HELO qmta03.westchester.pa.mail.comcast.net) (76.96.62.32) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Jan 2011 03:11:11 +0000 Received: from omta15.westchester.pa.mail.comcast.net ([76.96.62.87]) by qmta03.westchester.pa.mail.comcast.net with comcast id xDR71f0071swQuc53FAqV1; Wed, 19 Jan 2011 03:10:50 +0000 Received: from [192.168.1.201] ([69.143.109.145]) by omta15.westchester.pa.mail.comcast.net with comcast id xFAp1f00R38FjT13bFApu5; Wed, 19 Jan 2011 03:10:49 +0000 Message-ID: <4D365637.2090607@christopherschultz.net> Date: Tue, 18 Jan 2011 22:10:47 -0500 From: Christopher Schultz User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.13) Gecko/20101207 Thunderbird/3.1.7 MIME-Version: 1.0 To: Tomcat Users List Subject: Re: [OT] Setting HTTP response headers caching for 1 year doesn't work References: <4D32D59B.8020402@ice-sa.com> <4D32F58B.5050305@ice-sa.com> <4D35E60E.2010009@christopherschultz.net> <4D362C76.3000206@ice-sa.com> In-Reply-To: <4D362C76.3000206@ice-sa.com> X-Enigmail-Version: 1.2a1pre Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Virus-Checked: Checked by ClamAV on apache.org -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 André, (You always make me write so much code!) On 1/18/2011 7:12 PM, André Warnier wrote: > Christopher Schultz wrote: >> There's nothing magical about the first operand: you can cast any of the >> operands to trigger this promotion. > > Not quite true I think. See note below. You're right: you have to do it before the first truncation. > Well here you see the difference with Java. > Java seems to overflow without even a warning. Note that it's the Java compiler not the runtime that fails to deliver an error. The compiled C code happily overflows without any warning. Had I written the code using an array to store the operands and used an int to store the temporary result, you'd see the same truncation behavior with no compiler warnings. The fact that constants are being used are allowing the compiler to complain in this case. Revised code: $ cat longtime.c #include int main(int argc, char *argv[]) { int cacheTime1 = (1000 * 60 * 60 * 24 * 100 * 3); long cacheTime2 = ((long)1000 * 60 * 60 * 24 * 100 * 3); long long cacheTime3 = ((long long)1000 * 60 * 60 * 24 * 100 * 3); long long cacheTime4 = (1000 * 60 * 60 * 24 * 100 * (long long)3); printf("%d\n%ld\n%lld\n%lld\n", cacheTime1, cacheTime2, cacheTime3, cacheTime4); return 0; } cschultz@dev:~/projects/toys$ cc -ansi -pedantic -Wall -o longtime \ longtime.c && ./longtime longtime.c: In function `main': longtime.c:4: warning: integer overflow in expression longtime.c:5: warning: integer overflow in expression longtime.c:6: warning: ISO C90 does not support `long long' longtime.c:6: warning: ISO C90 does not support `long long' longtime.c:7: warning: ISO C90 does not support `long long' longtime.c:7: warning: integer overflow in expression longtime.c:7: warning: ISO C90 does not support `long long' longtime.c:9: warning: ISO C90 does not support the `ll' printf length modifier longtime.c:9: warning: ISO C90 does not support the `ll' printf length modifier 150196224 150196224 25920000000 150196224 So, the expression type escalation needs to happen before the first overflow in order for things to work out well. > Now the calculation overflows an int at the penultimate step (* 100), > and setting the last term to be a long does not help, it's too late. Not enough people use the word "penultimate": nice work. > I think that what happens is : > - the expression is evaluated from left to right, not in one single step > - multiplying an int by a long (in whatever order), is done in long mode > and generates a long Correct on both counts. >> Most languages' behavior are surprising to Perl programmers :) > > See below. > >> >> Seriously, though, these are the tradeoffs of a strongly-typed language: >> you have to be very precise about the way you want calculations to be >> performed. The compiler assumes that if you wanted double-precision >> integers, you'd ensure that the calculation is done using "long" and not >> "int". Presumably, 64-bit operations are (or were) considered slower >> than 32-bit operations and so require the coder to specify that 64-bit >> operations are desired. >> > At the cost of truncating the result and obtaining an incorrect one > surrepticiously and without a warning ? Well, at some point (such as non-constant calculations) overflow checks are either not possible (Java?) or not practical (C) at runtime. C and similar languages are well-documented to silently ignore overflow (or underflow for that matter) and it's up to the programmer to check for this kind of thing. Overflow checking is something that takes time, and the C language was designed to compile to minimal machine code. If the programmer cares about overflow, the programmer needs to check for it. Likewise, if a Java programmer wants to avoid overflow in all cases, he or she only need to use BigInteger for everything. Of course, performance totally sucks when using BigInteger, but hey, I don't think you'll ever overflow that (unless your BigInteger has something like 2^16 digits in it). > I would find : (long)(1000 * 60 * 60 * 24 * 365) > more intuitive, if it forced the calculation to be done in Long mode > (which I suspect it does not; it probably just "promotes" the truncated > result to long before the assignment). It does not: see the C code I posted. I would be surprised if Java acted differently, though I'm unwilling to write the code myself just now to test it. >> No, the clarity is in the fact that the target identifier should be able >> to store a double-precision value. It says nothing about calculations >> that are assigned to it. >> >> If you saw this, would the result (0.0) confuse you? >> >> double d = 1 / 2; > > It would not confuse me, because by now I am ready for anything. But I > would find this just as unintuitive and wrong, for exactly the same > reason. What kind of stupid compiler is this, which requires me to say > double d = 1.0 / 2; > to get a correct result ? It's one that produces seriously fast code: $ cat divisionSpeedTest.c #include #include #define ITERATIONS 100000000 int main(int argc, char *argv[]) { struct timeval start, end; int i; int integral; int ileft=1, iright=2; float decimal; float fleft = 1.0, fright=2.0; /* time empty loop */ gettimeofday(&start, NULL); /* start clock */ for(i=0; i And even then, if the expression was > double d = 1.0 / 3; > I would probably *still* not get a result with the precision afforded by > the double d, and would have to write > double d = 1.0D / 3; > to get it right, right ? Yup: float is the default decimal type. Double-precision takes longer, so you have to ask for it. $ cat precision.c #include int main(int argc, char *argv[]) { float f = 1.0 / 7; float ff = (1.0f / 7.0f); double d = 1.0 / 7; double dd = 1.0 / 7; printf("%1.10e\n%1.10e\n%1.10e\n%1.10e\n", f, ff, d, dd); return 0; } cschultz@dev:~/projects/toys$ cc -ansi -pedantic -Wall -o precision precision.c && ./precision 1.4285714924e-01 1.4285714924e-01 1.4285714286e-01 1.4285714286e-01 > I maintain what I said : a programming language which produces a wrong > result, without even a warning, for an expression as simple as > Long a = (1000 * 60 * 60 * 24 * 365) > should be consigned to iPods and stuff, not used for serious things like > Tomcat. There are people using iPads for healthcare. One would expect that precision counts, there, too. ;) > Incidentally, and since you mentioned it : > > C:\WINDOWS>perl > print (1000 * 60 * 60 * 24 * 365); > ^Z > 31536000000 Of course! It just takes a few million more cycles to do it. > That's what I call a smart and intuitive language.. Just not for the impatient. - -chris -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAk02VjcACgkQ9CaO5/Lv0PDCOQCglqCp8wMh/69GrDErUL2loORl H04An1lW8Pjq3xJnthVsDfQnuSAPyHmP =2m1U -----END PGP SIGNATURE----- --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org For additional commands, e-mail: users-help@tomcat.apache.org