tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From André Warnier ...@ice-sa.com>
Subject Re: [OT] Setting HTTP response headers caching for 1 year doesn't work
Date Wed, 19 Jan 2011 00:12:38 GMT
Christopher Schultz wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> André,
> 
> On 1/16/2011 8:41 AM, André Warnier wrote:
>> Ran Berenfeld wrote:
>>> well ...no... first evaluate, then assign. and constants are int by
>>> default.
>>> I think C/C++ would have the same problem...
>>>
>> Maybe.
> 
> FYI they do.
> 
>> But then why does the fact of specifying just the first
>> right-hand side constant in the calculation as a long, magically change
>> the whole result into a long ?
>> (1000 * 60 * 60 * 24 * 365)  --> int
>> (1000L * 60 * 60 * 24 * 365) --> long
> 
> Because it promotes the type of the entire expression to "long" and the
> laws change for the expression. The assignment works as usual.
> 
> 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.

Here's some C code that demonstrates
> it (note that Java's long is 64-bit so we need "long long" which has
> spotty ANSI support):
> 
> $ cat longtime.c
> #include <stdio.h>
> 
> int main(int argc, char *argv[]) {
>   int cacheTime1 = (1000 * 60 * 60 * 24 * 365);
>   long cacheTime2 = ((long)1000 * 60 * 60 * 24 * 365);
>   long long cacheTime3 = ((long long)1000 * 60 * 60 * 24 * 365);
>   long long cacheTime4 = (1000 * 60 * 60 * 24 * (long long)365);
> 
>   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

Well here you see the difference with Java.
Java seems to overflow without even a warning.
(Chuck tried to get a warning at compile time, without success.)

One additional remark about the calculations you show above (which also applies to Java) :
In (1000 * 60 * 60 * 24 * 365), the overflow occurs at the last step, when multiplying by
365.
So in this particular case you are right, the fact of setting *any* factor of the 
multiplication to be a long "saves the day", because subsequent operations will be done in

"long mode", and it is enough to make the last term a long, to avoid the problem.
However, suppose for the sake of argument that a year would have 300 days, and that 
instead the OP had expressed his duration like this :
(1000 * 60 * 60 * 24 * 100 * 3L)
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.
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
- so, in the original calculation
     1000 * 60 is done in int-mode, and generates an int R1
       R1 * 60 is done in int-mode, and generates an int R2
       R2 * 24 is done in int-mode, and generates an int R3
       R3 * 365 is done in int-mode, overflows, but still generates an int
- while
     1000 * 60 is done in int-mode, and generates an int R1
       R1 * 60 is done in int-mode, and generates an int R2
       R2 * 24 is done in int-mode, and generates an int R3
       R3 * 365L is done in long-mode, does not overflow, and generates a correct long

- but with the revised calculation (1000 * 60 * 60 * 24 * 100 * 3.65L):
     1000 * 60 is done in int-mode, and generates an int R1
       R1 * 60 is done in int-mode, and generates an int R2
       R2 * 24 is done in int-mode, and generates an int R3
       R3 * 100 is done in int-mode, generating an int R4 which is already truncated
       R4 * 3L would generate a long, but with the error magnified

...
> 
> 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 ?

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).

...

> 
> 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 ?
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 ?

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.
(No wonder after that, that lunar probes go CFIT.)

Incidentally, and since you mentioned it :

C:\WINDOWS>perl
print (1000 * 60 * 60 * 24 * 365);
^Z
31536000000

and even :

C:\WINDOWS>perl
print ("1000" * 60 * 60 * 24 * 365);
^Z
31536000000

and also
C:\WINDOWS>perl
print ("1000.0" * 60 * 60 * 24 * 365);
^Z
31536000000

That's what I call a smart and intuitive language..
:-)

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message