From: glathoud on 15 Jul 2010 03:40 Hello, I've just had the following issue in Safari 5: 0 == (0.17 * 2) >> 0 // -> true 0 == (0.17 * [0,1].length) >> 0 // -> false (!) and here is a possible workaround: a = (0.17 * [0,1].length) >> 0 0 == a // -> true (results are the same with ===) I hope this helps someone, Guillaume
From: Dr J R Stockton on 17 Jul 2010 14:58 In comp.lang.javascript message <3e7b3e7c-eb62-45b1-ba72-25e4cef86722(a)g1 9g2000yqc.googlegroups.com>, Thu, 15 Jul 2010 00:40:54, glathoud <glathoud(a)yahoo.fr> posted: >I've just had the following issue in Safari 5: > >0 == (0.17 * 2) >> 0 // -> true >0 == (0.17 * [0,1].length) >> 0 // -> false (!) > >and here is a possible workaround: > >a = (0.17 * [0,1].length) >> 0 >0 == a // -> true > >(results are the same with ===) > >I hope this helps someone, It would have more chance of doing so if the host system were stated. Safari seem to be singularly inept at helping users to update in a timely fashion; as far as I know, my Safari 4.0.5 is the latest Windows version. Under "Help" it has "Report Bugs to Apple" - were you able to do that? I don't see the error in 4.0.5. -- (c) John Stockton, nr London, UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME. Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links; Astro stuff via astron-1.htm, gravity0.htm ; quotings.htm, pascal.htm, etc. No Encoding. Quotes before replies. Snip well. Write clearly. Don't Mail News.
From: Swifty on 18 Jul 2010 01:44 On Sat, 17 Jul 2010 19:58:52 +0100, Dr J R Stockton <reply1028(a)merlyn.demon.co.uk> wrote: >as far as I know, my Safari 4.0.5 is the latest Windows >version. I have 5.0 and it must have come via the standard Apple software automatic updating process, as I did nothing explicit to obtain it. -- Steve Swift http://www.swiftys.org.uk/swifty.html http://www.ringers.org.uk
From: Ry Nohryb on 18 Jul 2010 04:46 On Jul 15, 9:40 am, glathoud <glath...(a)yahoo.fr> wrote: > > I've just had the following issue in Safari 5: > > 0 == (0.17 * 2) >> 0 // -> true > 0 == (0.17 * [0,1].length) >> 0 // -> false (!) navigator.userAgent --> "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-us) AppleWebKit/534.3+ (KHTML, like Gecko) Version/5.0 Safari/533.16" 0 == (0.17 * [0,1].length) >> 0 --> true 0 == (0.17 * [0,1].length) >>> 0 --> true -- Jorge.
From: Richard Cornford on 18 Jul 2010 11:21
On Jul 15, 8:40 am, glathoud wrote: > Hello, > > I've just had the following issue in Safari 5: > > 0 == (0.17 * 2) >> 0 // -> true > 0 == (0.17 * [0,1].length) >> 0 // -> false (!) I can confirm that in Windows Safari 5.0 (7533.16). > and here is a possible workaround: But the obvious question is what exactly is it this is supposed to be working around? Without being sure about what it is that is being 'worked around' there is a risk of introducing another mystical incantation into javascript development. > a = (0.17 * [0,1].length) >> 0 > 0 == a // -> true > > (results are the same with ===) That comment implies that the issue is with the comparison operator. However, document.write( '((0.17 * [0,1].length) >> 0) -> '+ ((0.17 * [0,1].length) >> 0) ); - outputs:- ((0.17 * [0,1].length) >> 0) -> 0.3399999141693115 So it is not the comparison that is the issue. The expression is evaluating to a non-integer value, which it never should because the right shift bitwise operation should only act on 32 bit integers by converting its operands into numbers and then 32 bit integers. The multiplication can be dismissed from consideration by:- document.write('(Math.PI >> 0) -> '+(Math.PI >> 0)); - outputting:- (Math.PI >> 0) -> 3.1415920257568373 So the issue is with the right shift operator, and not just with shifting by zero as:- document.write('(Math.PI >> 3) -> '+(Math.PI >> 0)); - outputs:- (Math.PI >> 3) -> 3.141592025756836 (Note that this value is not the same as for >> 0, and that neither value shown is Math.PI (both operations have had some impact on the input value)) However, the right shift operator is apparently not totally defective as:- document.write( '(3.141592653589793 >> 0) -> '+ (3.141592653589793 >> 0) ); - outputs:- (3.141592653589793 >> 0) -> 3 -and:- var m = Math.PI; document.write('(m >> 0) -> '+(m >> 0)); - outputs:- (m >> 0) -> 3 - which are correct. On the other hand:- function u(){return 4.5;} document.write('(u() >> 1) -> '+(u() >> 1)); - outputs:- (u() >> 1) -> 4.500000000000002 (Note that 4.5 is a number that IEEE double precision floating point numbers can represent precisely, so again this shift operation has modified the number.) - while:- function v(){return 4;} document.write('(v() >> 1) -> '+(v() >> 1)); - outputs:- (v() >> 1) -> 2 This suggests that where the left hand side operand of the shift expression results in an integer value the shift operation will work correctly (other tests reinforce this impression). However, it turns out that the right hand side operand also has an impact:- document.write('(Math.PI >> -0) -> '+(Math.PI >> -0)); - outputs:- (Math.PI >> -0) -> 3 - which is correct. In javascript it should not be possible to discriminate between -0 and +0, but here apparently you can. this makes a possible work around for right shifting by zero to actually right shift by -0, but that does not help if you wanted to shift by some other value. Note that from this point on I am dropping the - document.write - from the examples to save space. Each of the following tests had the same form as the previous ones. This does, however, suggest for a feature test as:- ((Math.PI >> 0) == (Math.PI >> -0)) - should be true in ES3/5 conforming environments but not true in an environment where (Math.PI >> 0) comes out as 3.1415920257568373. However, on Windows Safari 5 this came out as true. Which suggest that in this context the (Math.PI >> 0) expression evaluated to the correct value. Reversing the expression to:- (Math.PI >> -0) == (Math.PI >> 0)) - produced the aberrant false in Windows Safari 5, as did:- ((Math.PI >> 0) == (Math.PI >> 0)) So we are looking at a single expression that fails in one context and succeeds in another. The implication is that it is the expression to the right of the equality operator that is failing, but it would be a good idea to confirm that, and to see if the equality operator itself is involved in this particular quirk. So:- ((Math.PI >> 0) - (Math.PI >> 0)) -> -0.14159202575683727 ((Math.PI >> 1) - (Math.PI >> 1)) -> -2.1415920257568364 ((Math.PI >> 1) / (Math.PI >> 1)) -> 0.3183099497965817 (Correct evaluation results should be zeros for the subtractions and one for the division). Asymmetrical results are found for subtraction and division operations, and the asymmetry shows that it is the right hand side operand expression that is failing, while the left hand operand expression is being correctly evaluated. This raises the question of what happens with increasing numbers of expressions, so:- (((Math.PI >> 0) - (Math.PI >> 0)) / (Math.PI >> 0)) Results in -0.04507015061025516, which is (((3) - (3.1415920257568373)) / (3.1415920257568373)) and show that the left most expression evaluated correctly but both of the following expressions failed. Then:- (((Math.PI >> 0) - (Math.PI >> 0)) - ((Math.PI >> 0) / (Math.PI >> 0))) Results in -1.096521875146582, which is ((3 - 3.1415920257568373) - (3 / 3.1415920257568373)), so the left most expression is correct, then next incorrect, the next correct, and the rightmost incorrect. A pattern may emerge if this was continued, but does not seem worth pursuing. It is clear that these failures of shift expressions are sensitive to the context in which the expression appears. However, notice that:- (((Math.PI >> 0) - (4.5 >> 0)) / (Math.PI >> 0)) Resutls in -0.27323979918632646 --> (((3.1415920257568373) - (4)) / (3.1415920257568373)), and:- (((Math.PI >> 0) - (u() >> 0)) / (Math.PI >> 0)) Results in -0.47746492469487356 --> (((3) - (4.5000000000000036)) / (3.1415920257568373)) (where - u - is the function that returns 4.5 defined above) - shows the leftmost (Math.PI >> 0) expression fail in one case and succeed in another. Tests on other bitwise operators show precisely the same issue for unsigned right shift ( >>> ), but no issues with bitwise OR ( | ). If you wanted a workaround for this particular Safari 5 bug then I would suggest replacing all occurrences of - >> 0 - (right shift zero bits) with - | 0 - (bitwise OR with zero), as that would have the same truncating side effect for a negligible loss of performance in other browsers, and when shifting by other numbers of bits, because the shift expression seems to always be successful when applied to integer values, it should be practical to apply - | 0 - to the left hand side operand prior to the application of the shift operation. That is (Math.PI >> 1) becomes ((Math.PI | 0) >> 1). The effect would be less disruptive (less obfuscating) than introducing new local variables to hold the results of pre-evaluated expressions. On the other hand, I would recommend doing nothing at all and letting Safari 5 suffer for its faults. For one thing, if a web browser wants to advertise itself as being the fastest browser ever it would be hypocritical for it (though its bugs) to force developers to use workarounds that harm the performance of all of its competitors. The second reason is that if Safari 5 has been allowed out of the door with this ridiculous context-sensitive f**k up of a simple low-level operation in place the odds are really good that there are more. These days it does not seem sensible to start making new concessions for new web browsers that cannot even conform to the basics of the ten year old ES 3 standard. Richard. |