Hi all,
I was just updating the dec[bin|hex|oct] functions to convert numbers >=
2^32 since the [bin|hex|oct]dec counterparts were updated way back in PHP
4.1.
My question is if negative numbers should be handled any differently. Now
negative longs are converted to unsigned which gives a weird result for
regular users IMO. The dec() functions ignore negative strings. Because
of the way base_convert()
works, if you pass a negative number (gets
converted to string), the result will be from the absolute value instead of
what you get with dec().
) Should the dec() functions continue to convert negative longs to
unsigned and use absolute value for doubles?
*) Should absolute value always be used, like with base_convert()
?
*) Should everything be changed to support negative numbers going both
directions (to or from base)?
Thanks,
Matt
Hi again,
I realize I might not get any answer about updating these little ol'
functions :-/, but it'd be nice to hear something one way or the other so I
can submit an acceptable patch with correct behavior.
After thinking about it more, are negative numbers even "officially
supported" with the dec[bin|hex|oct] functions? You won't get anything
close to the original back with dec(dec(-123)).
Since base_convert()
uses the number's absolute value, I'm thinking the only
reason for using "unsigned long" for the dec*() functions is to handle cases
where a PHP double is between LONG_MAX and ULONG_MAX. If so, I think
absolute value can be used everywhere.
Or again, should I update the functions to correctly accept and return
negative values? But I'm not sure if negative bin/hex/oct strings are
desired (semantically).
Thanks for any simple guidance!
Matt
----- Original Message -----
From: "Matt W"
Sent: Wednesday, July 26, 2006
Hi all,
I was just updating the dec[bin|hex|oct] functions to convert numbers >=
2^32 since the [bin|hex|oct]dec counterparts were updated way back in PHP
4.1.My question is if negative numbers should be handled any differently. Now
negative longs are converted to unsigned which gives a weird result for
regular users IMO. The dec() functions ignore negative strings. Because
of the waybase_convert()
works, if you pass a negative number (gets
converted to string), the result will be from the absolute value instead
of
what you get with dec().) Should the dec() functions continue to convert negative longs to
unsigned and use absolute value for doubles?*) Should absolute value always be used, like with
base_convert()
?*) Should everything be changed to support negative numbers going both
directions (to or from base)?Thanks,
Matt
Matt W wrote:
Hi again,
[...]
I don't see what you're trying to fix.
$ cli -r 'var_dump((int)hexdec(dechex(-123)), (int)(float)sprintf("%u",-123), (int)0xffffff85);'
int(-123)
int(-123)
int(-123)
Regards,
Michael
Hi Michael,
----- Original Message -----
From: "Michael Wallner"
Matt W wrote:
Hi again,
[...]
I don't see what you're trying to fix.
$ cli -r 'var_dump((int)hexdec(dechex(-123)),
(int)(float)sprintf("%u",-123), (int)0xffffff85);'
int(-123)
int(-123)
int(-123)
The main "fix" (upgrade) is to let the dec*() functions convert numbers >=
2^32. But I'm wondering whether this should be changed:
C:\math-old>php -r "var_dump(hexdec(dechex(-123)));"
float(4294967173)
Your (int) typecast changed that of course.
If the dec*() functions handle numbers whose absolute value is >= 2^32, how
is a negative double supposed to be handled? Absolute value, I assume. But
that's different than negative int handling now (internal long converted to
unsigned long). If double's were to be the same way, and there was an
unsigned double type, passing -5000000000 would result in an insanely huge
number after being made "unsigned" internally like now.
That's why I'm assuming negative numbers aren't "really" supported now (not
in any form with base_convert()
), but it's simply a side effect of wanting
to handle positive numbers between LONG_MAX and ULONG_MAX. e.g. when
doing dechex(4294967173) that's a PHP double, but it gets converted to long
(becomes -123), and finally unsigned long (recovering 4294967173). IOW,
after convert_to_long() in dec*() it doesn't know if -123 or 4294967173 was
passed. Make sense? (Actually, it doesn't, that's my point. :-))
So after more thinking, I figure when upgrading dec*() to handle any number,
absolute value should be used (then int(123) would be returned in my
example). Unless the all the functions are changed to properly
accept/return negatives... I personally don't care either way on that.
Regards,
Michael
Matt
Matt W wrote:
That's why I'm assuming negative numbers aren't "really" supported
now (not in any form withbase_convert()
), but it's simply a side
effect of wanting to handle positive numbers between LONG_MAX and
ULONG_MAX. e.g. when doing dechex(4294967173) that's a PHP double,
but it gets converted to long (becomes -123), and finally unsigned
long (recovering 4294967173). IOW, after convert_to_long() in dec*()
it doesn't know if -123 or 4294967173 was passed. Make sense?
(Actually, it doesn't, that's my point. :-))
For your computer 0xffffff85 is -123 and 4294967173. It's just how
you look on it.
So after more thinking, I figure when upgrading dec*() to handle any
number, absolute value should be used (then int(123) would be
returned in my example). Unless the all the functions are changed to
properly accept/return negatives... I personally don't care either
way on that.
No way. Why should hexdec(dechex(-123)) return +123?
--
Michael
Hi Michael,
----- Original Message -----
From: "Michael Wallner"
Sent: Thursday, July 27, 2006
Matt W wrote:
That's why I'm assuming negative numbers aren't "really" supported
now (not in any form withbase_convert()
), but it's simply a side
effect of wanting to handle positive numbers between LONG_MAX and
ULONG_MAX. e.g. when doing dechex(4294967173) that's a PHP double,
but it gets converted to long (becomes -123), and finally unsigned
long (recovering 4294967173). IOW, after convert_to_long() in dec*()
it doesn't know if -123 or 4294967173 was passed. Make sense?
(Actually, it doesn't, that's my point. :-))For your computer 0xffffff85 is -123 and 4294967173. It's just how
you look on it.
Oh, I know. But that still doesn't answer the question of how to handle
negative double's.
So after more thinking, I figure when upgrading dec*() to handle any
number, absolute value should be used (then int(123) would be
returned in my example). Unless the all the functions are changed to
properly accept/return negatives... I personally don't care either
way on that.No way. Why should hexdec(dechex(-123)) return +123?
Because it makes more sense to users than 4294967173? :-) They don't care
what's stored as 0xffffff85, blah blah, just what they actually see. Oh,
and doing the same to/from using -123 and base_convert()
, you'll get +123!
IMO, it was wrong to convert a negative to unsigned long. Absolute value
should've been used like with base_convert (though that may be by chance
rather than design :-)). Of course, it could all be very
consistent/logical, to me, by accepting/returning negatives. But what are
the thoughts on negative base 2-36 strings? No-no's?
--
Michael
I appreciate your replies. I'll be gone for a while now, so I won't be
bothering you with another e-mail. :-P
Matt
Hi,
More thoughts...
I forgot to say last time that the manual doesn't mention the dec*()
parameter being treated as unsigned. The *printf() specifiers b/o/x/X
already do this (although the manual doesn't say that either, only for %u).
After looking through the comments for dechex()
, there's another thing: 32-
vs 64-bit. On a 64-bit system, I think dechex(-123) would currently return
ffffffffffffff85, which when reversed on my system gives
php -d precision=20 -r "var_dump(hexdec('ffffffffffffff85'));"
float(18446744073709552000)
Are you saying, Michael, that the negative behavior should be left as-is for
people to see "how the number is stored by the computer?" I think just
using the printf() specifiers would better. IMO, the dec() and *dec()
functions should work the same as the corresponding to/from base with
base_convert()
(absolute value), and vice-versa.
BTW, can base_convert()
simply return an actual number instead of a string
when tobase=10? Again, to be the same as *dec() and avoid conversion to
string if it's just going to be used in numeric context.
Matt
----- Original Message -----
From: "Michael Wallner"
Sent: Thursday, July 27, 2006
Matt W wrote:
That's why I'm assuming negative numbers aren't "really" supported
now (not in any form withbase_convert()
), but it's simply a side
effect of wanting to handle positive numbers between LONG_MAX and
ULONG_MAX. e.g. when doing dechex(4294967173) that's a PHP double,
but it gets converted to long (becomes -123), and finally unsigned
long (recovering 4294967173). IOW, after convert_to_long() in dec*()
it doesn't know if -123 or 4294967173 was passed. Make sense?
(Actually, it doesn't, that's my point. :-))For your computer 0xffffff85 is -123 and 4294967173. It's just how
you look on it.So after more thinking, I figure when upgrading dec*() to handle any
number, absolute value should be used (then int(123) would be
returned in my example). Unless the all the functions are changed to
properly accept/return negatives... I personally don't care either
way on that.No way. Why should hexdec(dechex(-123)) return +123?
--
Michael
Hi again,
OK, after my last message, I found when the dec*() functions started
converting to unsigned long (Bug #6761). To make dechex(~8) etc. work. Now
I know that behavior can't change. :-) Hopefully this is my last e-mail
about this, if I can please find out about 2 simple things:
- How should a negative double, whether it's < LONG_MIN or typecast
(double) -123, be handled?
*) Continue converting to long/unsigned long, like now?
*) Use absolute value? (Only if double!)
Either way, base_convert()
should continue to use absolute value for all
numbers, I assume.
- CAN
base_convert()
be changed to return an actual number instead of a
string if tobase=10? Seems a waste to convert a base 10 result to string
like now... :-?
Thanks!
Matt
----- Original Message -----
From: "Matt W"
Sent: Friday, July 28, 2006
Hi,
More thoughts...
I forgot to say last time that the manual doesn't mention the dec*()
parameter being treated as unsigned. The *printf() specifiers b/o/x/X
already do this (although the manual doesn't say that either, only for
%u).After looking through the comments for
dechex()
, there's another thing:
32-
vs 64-bit. On a 64-bit system, I think dechex(-123) would currently
return
ffffffffffffff85, which when reversed on my system givesphp -d precision=20 -r "var_dump(hexdec('ffffffffffffff85'));"
float(18446744073709552000)Are you saying, Michael, that the negative behavior should be left as-is
for
people to see "how the number is stored by the computer?" I think just
using the printf() specifiers would better. IMO, the dec() and *dec()
functions should work the same as the corresponding to/from base with
base_convert()
(absolute value), and vice-versa.BTW, can
base_convert()
simply return an actual number instead of a string
when tobase=10? Again, to be the same as *dec() and avoid conversion to
string if it's just going to be used in numeric context.Matt