On Sun, 2004-05-16 at 17:17, Ard Biesheuvel wrote: > Hi Timm, > > I have an old Alpha PWS433 running FreeBSD which I use for this kind of > stuff. > > > If so, what does this print? > > -------------------------------------------------------------------------- > > #define LONG_MAX 2147483647L > > #define LONG_MIN (- LONG_MAX - 1) > > Use this for portability > > #define LONG_MIN (1L << 8*sizeof(long)-1) > #define LONG_MAX ~LONG_MIN
Urm... yes:) LONG_MAX is definitely not 2147483647L on 64-bit:) > > int main(int argc, char* argv) > > { > > printf("1) %s\n", (double)LONG_MAX + 1 > LONG_MAX ? "+OK" : "-ERR"); > > printf("2) %s\n", (double)LONG_MIN - 1 < LONG_MIN ? "+OK" : "-ERR"); > > } > > 1) -ERR > 2) -ERR OK, I found some discussion on this topic using Google. If I understand correctly, double on 64-bit platforms isn't accurate enough to hold a long, right? > > I thought this code was OK by looking at the following: > > > > Zend/zend_operators.c:#define DVAL_TO_LVAL(d, l) (l) = (d) > LONG_MAX ? > > (unsigned long) (d) : (long) (d) > > The problem in your code wasn't the comparison per se, but the > conversion from long to double and back. You will lose accuracy by doing > that. The value you're converting started out as a long, didn't it ? Nope, before the first conversion it's actually a string (see php_sybase_ct.c, lines 1131 to 1123). To bring this discussion to an end: How does the portable solution look like? Or, to be more specific, what would need to be done for this to work portably: -- snip -- Z_STRLEN(result->data[i][j]) = result->lengths[j]-1; Z_STRVAL(result->data[i][j]) = estrndup(result->tmp_buffer[j], result->lengths[j]); Z_TYPE(result->data[i][j]) = IS_STRING; /* Now I want to figure out whether this fits into a long, * and if it does, make it one, a double otherwise */ -- snip -- Possible ideas would be to use strtol and check for ERANGE (sample attached). - Timm
#include <stdlib.h> #include <stdio.h> #include <limits.h> #include <errno.h> #define STRTOLD(str, fits, l, d) \ errno = 0; \ l= strtol(argv[1], NULL, 10); \ if (errno == ERANGE) { \ d= strtod(argv[1], NULL); \ fits = 0; \ } else { \ fits = 1; \ } \ int main(int argc, char** argv) { long l; double d; int fits; if (argc != 2) { fprintf(stderr, "Usage: %s <number>\n", argv[0]); return 1; } STRTOLD(argv[1], fits, l, d); if (fits) { printf("Fits into a long: %ld\n", l); } else { printf("Does not fit into a long, made it a double: %.0f\n", d); } return 0; }
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php