Open 837951602 opened 7 years ago
It may be an idea to write -999999 as -1000000+1, and 1e12+1 to 1e12+1 but I don't know whether it's easy or difficult to achieve
1.0000000000001e+113 +(+(+!![]+(!![]+[])[!![]+!![]+!![]]+(+!![])+(!![]+!![]+!![]))+(+!![])+(!![]+[])[!![]+!![]+!![]]+(+!![])+(+[])+(+[]))
-999999 can be written as -1000000 + 1 and 1e12+1 as 1e12+1, that's fine because those are integers between Number.MAX_SAFE_INTEGER
and -Number.MAX_SAFE_INTEGER
. It wouldn't be too difficult either.
I'm not sure about 1.0000000000001e+113: this is a floating-point number that is only approximately equal to the sum of two powers of 10. Nothing in ECMAScript or IEEE-754 says that it couldn't be rounded to something slightly larger or slightly smaller, but most of all I don't know how consistent different engines are when calculating the sum of non-safe integers. JScrewIt must work with many different engines and I wouldn't be surprised if something that gives 1.000...0001 in my browser gave 1 in another one's browser. Long story short: this needs more experimentation and extensive testing if we don't want to break something accidentally.
JavaScript Numbers are Always 64-bit Floating Point Unlike many other programming languages, JavaScript does not define different types of numbers, like integers, short, long, floating-point etc.
JavaScript numbers are always stored as double precision floating point numbers, following the international IEEE 754 standard.
This format stores numbers in 64 bits, where the number (the fraction) is stored in bits 0 to 51, the exponent in bits 52 to 62, and the sign in bit 63:
Value (aka Fraction/Mantissa) Exponent Sign 52 bits (0 - 51) 11 bits (52 - 62) 1 bit (63) Precision Integers (numbers without a period or exponent notation) are considered accurate up to 15 digits.
Example var x = 999999999999999; // x will be 999999999999999 var y = 9999999999999999; // y will be 10000000000000000 Try it Yourself » The maximum number of decimals is 17, but floating point arithmetic is not always 100% accurate:
I'm not sure about 1.0000000000001e+113: this is a floating-point number that is only approximately equal to the sum of two powers of 10.
The expression is not 1e113+1e100
but +((1e13+1)+'e100')
@837951602 Ah, I see. But why not +(1e12+'1e100')
? That could be implemented as a string cluster optimization, specifically for the case of a string containing a nonzero digit followed by many zeros.
Yes +(1e12+'1e100')
is a better choice yet +((1e10+1)+'e100')
is shorter than +(1e9+'1e100')
1e-292
+(+!![]+(!![]+[])[!![]+!![]+!![]]+(+((+(+!![]+[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+!![])+(+[]))+[])[+!![]]+(+[])+(+[])+(+[])+(+[])+(+[])+(+[])+(+[])+(+[])+(+[])+(+!![]))+[])[!![]+!![]]+(!![]+!![])+(!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![])+(!![]+!![]))
259c
+(1+'e'+(10-302))
+(+!![]+(!![]+[])[!![]+!![]+!![]]+(+(+!![]+[+[]])+(+((+((+(+!![]+[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+!![])+(+[]))+[])[+!![]]+(+[])+(+[])+(+[])+(+[])+(+[])+(+[])+(+[])+(+[])+(+[])+(+!![]))+[])[!![]+!![]]+(!![]+!![]+!![])+(+[])+(!![]+!![])))))
245c
same type of -999999 as -1000000+1
Not sure about if float values or exceeded_safe_integer calculated get the same value? If so, 0.9999999999999998(822c) can't be +('.'+(1e16-2))(323c) or 1-2e-16(339c) but only +('.'+(1e15-1)+8)(358c)
So why is '-' translated into "1e-10"[2] instead of "1e-7"[2]? If because of compatible why no this feature
1e-100 208c +(1e-10+[0]) 146c
I don't know why "-" is defined how it is! This should be analyzed ASAP.
(ECMA-262 5th edition December 2009, P48) http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262%205th%20edition%20December%202009.pdf 9.8.1 ToString Applied to the Number Type The abstract operation ToString converts a Number m to String format as follows:
aemkei's jsfuck main page also said "0.0000001"->'1e-7' and get '-'. but creating it's 1e-10 https://github.com/aemkei/jsfuck/commit/4a5ff0e608fa4ac84dce3b7be70492ac9750ad0c
Made a branch to test the "-" optimization: https://github.com/fasttime/JScrewIt/tree/minus-sign. Looks good so far. @837951602 Kudos for spotting this!
9.999999999999997e+214
870c
+'999999999999999.7e200'
865c
There should only beWith x being a positive finite number, turning x to XXXeYYY style usesXXXeYYY
and(AAA)(.BBB)
-- since point costs 72 chars far larger than '9' 47, it's never cheap to use both.x.toExponential().replace(/^(\d)\.?(\d*)e(.*)$/,function(x,a,b,c){return a+b+'e'+(c-b.length)})
and to (AAA)(.BBB) useNumber.prototype.forceFixed=function(){var t=this.toString().split('e');if(t.length==1)return t.replace(/^0/,'');t[0]=t[0].replace(/\./,'');return t[1]>0?t[0]+Array(2- -t[1]-t[0].length).join(0):'.'+Array(-t[1]).join('0')+t[0]}
? (code not tested fully)