Closed
Bug 7625
Opened 26 years ago
Closed 26 years ago
Number.toString(base != 10) not working for negative numbers
Categories
(Core :: JavaScript Engine, defect, P3)
Tracking
()
RESOLVED
FIXED
M9
People
(Reporter: martin.honnen, Assigned: rogerl)
References
()
Details
Calling
toString(base)
with a base != 10 on a negative number returns utter nonsense
js> for (var n = -1; n > -11; n--) print (n.toString(16))
/
.
-
,
+
*
)
(
'
&
I guess that is not what ECMA calls implementation dependant. Happens
consistently with communicator on win95 and linux and with js1.4-2 (built on
linux).
Updated•26 years ago
|
Assignee: norris → rogerl
Comment 1•26 years ago
|
||
Looks like a bug. Rhino appears to have the correct behavior.
the behavior in this case is not actally specified in ecma though i agree it's
pretty crappy default behav ior. here's what it says:
15.7.4.2 Number.prototype.toString(radix)
If the radix is the number 10 or not supplied, then this number value is given
as an argument to the ToString operator; the resulting string value is
returned.
If the radix is supplied and is an integer from 2 to 36, but not 10, the result
is a string, the choice of which is implementation-dependent.
The toString function is not generic; it generates a runtime error if its this
value is not a Number object. Therefore, it cannot be transferred to other
kinds of objects for use as a method.
Reporter | ||
Comment 3•26 years ago
|
||
Are you using another rhino than the one available as rhinotip on mozilla.org as
that one doesn't seem to have
Number.toString(base)
but simply ignores any argument.
So what is correct behaviour for negative numbers, what
java.lang.Integer.toString(n, base)
does (taking the abs value and prefixing with - if needed) or what
java.lang.Integer.toHex/Binary/OctalString(n)
does (regarding the number as an unsigned int and converting to base 16/8/2)?
JScript seems to use the abs value and prefix with - if needed. Probably easier
to implement/add as a fix.
Reporter | ||
Comment 4•26 years ago
|
||
I tried to fix Number.toString to treat the Number as unsigned (as
java.lang.Integer.toHexString() does) to get meaningful results for negative
numbers and it seems to work:
static JSBool
num_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsval v;
jsdouble d;
jsint base, dval;
unsigned int ival; // changed that from jsint to unsigned int
char *bp, buf[32];
JSString *str;
if (!JS_InstanceOf(cx, obj, &number_class, argv))
return JS_FALSE;
v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
if (!JSVAL_IS_NUMBER(v))
return js_obj_toString(cx, obj, argc, argv, rval);
d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
if (argc != 0) {
if (!js_ValueToECMAInt32(cx, argv[0], &base))
return JS_FALSE;
if (base < 2 || base > 36) {
char numBuf[12];
JS_snprintf(numBuf, sizeof numBuf, "%ld", (long) base);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_RADIX,
numBuf);
return JS_FALSE;
}
if (base != 10 && JSDOUBLE_IS_FINITE(d)) {
ival = (unsigned int) js_DoubleToInteger(d); // changed the cast here
bp = buf + sizeof buf;
for (*--bp = '\0'; ival != 0 && --bp >= buf; ival /= base) {
dval = ival % base;
*bp = (char)((dval >= 10) ? 'a' - 10 + dval : '0' + dval);
}
if (*bp == '\0')
*--bp = '0';
str = JS_NewStringCopyZ(cx, bp);
} else {
str = js_NumberToString(cx, d);
}
} else {
str = js_NumberToString(cx, d);
}
if (!str)
return JS_FALSE;
*rval = STRING_TO_JSVAL(str);
return JS_TRUE;
}
That seems to improve things for negative numbers without changing anything for
positive
js> for (var n = -1; n > -20; n--) print(n + ': ' + n.toString(8))
-1: 37777777777
-2: 37777777776
-3: 37777777775
-4: 37777777774
-5: 37777777773
-6: 37777777772
-7: 37777777771
-8: 37777777770
-9: 37777777767
-10: 37777777766
-11: 37777777765
-12: 37777777764
-13: 37777777763
-14: 37777777762
-15: 37777777761
-16: 37777777760
-17: 37777777757
-18: 37777777756
-19: 37777777755
js> for (var n = -1; n > -20; n--) print(n + ': ' + n.toString(16))
-1: ffffffff
-2: fffffffe
-3: fffffffd
-4: fffffffc
-5: fffffffb
-6: fffffffa
-7: fffffff9
-8: fffffff8
-9: fffffff7
-10: fffffff6
-11: fffffff5
-12: fffffff4
-13: fffffff3
-14: fffffff2
-15: fffffff1
-16: fffffff0
-17: ffffffef
-18: ffffffee
-19: ffffffed
Comment 5•26 years ago
|
||
You're right that Rhino ignores the argument to Number.prototype.toString
entirely. That's a bug that should be fixed.
Assignee | ||
Updated•26 years ago
|
Status: NEW → ASSIGNED
Assignee | ||
Updated•26 years ago
|
Status: ASSIGNED → RESOLVED
Closed: 26 years ago
Resolution: --- → FIXED
Assignee | ||
Comment 7•26 years ago
|
||
Fixed in SpiderMonkey & Rhino by returning '-' + toString(abs(n), base) for
negative numbers.
js> (-10).toString(16)
-a
this still seems kind of wrong -- seems like it should return "-0xa". if we
don't, we get this:
js> (-10).toString(16)
-a
js> Number( (-10).toString(16) )
NaN
js> Number( "-0xa" )
-10
Assignee | ||
Updated•26 years ago
|
Status: REOPENED → ASSIGNED
Assignee | ||
Comment 9•26 years ago
|
||
Gets uglier by the minute. According to my reading, Number("-0xa") should have
returned NaN since a "-" is only allowed to precede a decimal literal. In which
case, maybe I should back out the change in favor of treating bases other than
10 as unsigned.
Comment 10•26 years ago
|
||
wait a sec -- who're you saying is getting uglier by the minute?!
Comment 11•26 years ago
|
||
okay, i take it back. making it hex is not right.
js> (10).toString(16)
its been a while since i've been in the spec.
Comment 12•26 years ago
|
||
Clearing Fixed resolution due to ReOpen of this bug.
Comment 13•26 years ago
|
||
Moving from M7 to M9. M7 is long gone :-)
Assignee | ||
Updated•26 years ago
|
Status: ASSIGNED → RESOLVED
Closed: 26 years ago → 26 years ago
Resolution: --- → FIXED
Assignee | ||
Comment 14•26 years ago
|
||
O.K. since you changed your mind, I'm going to stick by my original decision to
treat the value as signed and just leave it this way.
You need to log in
before you can comment on or make changes to this bug.
Description
•