hexdec
Converts a hexadecimal string to its decimal number equivalent.
hexdec(string $hex_string): int|float- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$hex_string | string | The hexadecimal string to convert. Non-hexadecimal characters are ignored. |
Return value
int|floatThe decimal value of $hex_string. Returns int when the value fits the platform integer range, otherwise float.
Errors
Does not throw for invalid characters; it emits a deprecation notice and skips them. A TypeError is raised only if the argument is not a string or string-coercible value.
Changelog
- PHP 7.4.0Passing invalid characters now generates a deprecation notice. The result is still computed as though those characters were not present.
hexdec() reads a base-16 string and returns its decimal value. It is the inverse of dechex(), and it expects bare digits — no 0x prefix, no #.
When to reach for it
Parsing hex colour codes into RGB components is the everyday case. Beyond that: decoding byte values from a hex dump, reading identifiers or flags from protocol headers, and unpacking values from formats that store numbers in hex text.
What trips people up
The function ignores anything that is not a hex digit rather than rejecting it. hexdec("#ff") and hexdec("0xff") both return 255, and the surprising one, hexdec("that"), returns 10 because only the a counts. Since PHP 7.4 this raises a deprecation notice, but it still returns a number, so bad input becomes a plausible-looking wrong value instead of an error. Validate first with ctype_xdigit() when the string comes from users.
The return type shifts. Values up to PHP_INT_MAX come back as int; anything larger silently becomes a float and loses exact precision, so a 16-character hash fragment will not round-trip. Use the GMP extension for those.
Note also that hexdec() has no concept of sign — hexdec(dechex(-1)) gives a large positive float, not -1.
Example
When to use it
- Split a CSS colour like ff6347 into its red, green and blue decimal components.
- Decode byte values from a hex dump or a hex-encoded protocol field.
- Read a numeric identifier stored as hexadecimal text in a log or config file.
Frequently asked questions
Why does hexdec return a wrong number for an invalid string?
hexdec() skips any character that is not a hex digit rather than failing, so hexdec("that") returns 10 from the single a. Since PHP 7.4 it emits a deprecation notice; validate with ctype_xdigit() first.
Can hexdec handle a 0x prefix?
Not properly. hexdec("0xff") happens to return 255 because x is skipped and the leading 0 is harmless, but it triggers a deprecation notice. Strip the prefix yourself, or use intval("0xff", 16) or intval("0xff", 0).
Why does hexdec return a float for long hex strings?
Values above PHP_INT_MAX cannot fit in an int, so hexdec() returns a float instead. Floats hold about 15-16 significant digits, so the exact value is lost — use gmp_init($hex, 16) when precision matters.
More examples
Validating before converting
Only ff and #1a2b convert, giving 255 and 6699. The strings that hexdec() would quietly mangle — "that" becoming 10 and "0xff" becoming 255 by skipping the x — return null instead, and ctype_xdigit() keeps the deprecation notice from ever firing.
<?php
function parseHex(string $s): ?int {
$s = ltrim($s, '#');
if ($s === '' || !ctype_xdigit($s)) {
return null;
}
return (int) hexdec($s);
}
foreach (["ff", "#1a2b", "that", "0xff", ""] as $in) {
var_dump(parseHex($in));
}Expanding a shorthand colour code
Both calls return [255, 136, 0]. The three-digit shorthand is expanded by doubling each character before splitting, which is exactly how browsers interpret #f80, and str_split with a length of 2 feeds hexdec() one byte at a time.
<?php
function toRgb(string $hex): array {
$hex = ltrim($hex, '#');
if (strlen($hex) === 3) {
$hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
}
return array_map('hexdec', str_split($hex, 2));
}
print_r(toRgb('#f80'));
print_r(toRgb('#ff8800'));Where int turns into float
7fffffffffffffff is PHP_INT_MAX and returns an int. One more than that crosses into float, where the value is approximate and the low bits are gone. The final check shows negatives never round-trip, because hexdec() has no notion of sign.
<?php
foreach (["7fffffffffffffff", "8000000000000000", "ffffffffffffffff"] as $h) {
$v = hexdec($h);
printf("%-18s %-8s %s\n", $h, get_debug_type($v), var_export($v, true));
}
var_dump(hexdec(dechex(-1)) === -1);
Discussion