3 Answers
3

To understand what's happening, the difference between evaluation and parsing needs to be made clear:

parsing means taking the string (the text) input to Mathematica and converting it to some internal representation of a Mathematica expression

evaluation means taking a Mathematica expression and transforming it according to some rules the evaluator knows about

The string 16^^abcdef gets directly parsed into an Integer. 11259375 gets parsed to the very same integer. The way Mathematica stores integers internally does not include the base in which the number was originally. 16^^abcdef and 11259375 are two ways to write the exact same Mathematica expression.

The information about the base is lost at parse time, the evaluator never sees it.

If you read 16^abcdef as input interactively or from a file, you need to make sure you read it as a string (e.g. InputString) and avoid parsing it into a Mathematica expression. Then you can analyse the string an find out what is the base.

You can see that the base never survives to the evaluation stage by trying for example

16^^98 // Unevaluated // AtomQ

True

16^^98 // Unevaluated // Head

Integer

Trace[16^^98, TraceInternal -> True]

{}

It's more or less like a box formatting rule. The Front End sends the literal structure to the kernel, it first builds up the expression, and then when the real evaluation starts, it has already been turned into an integer.

You could mess with this, plugging yourself in at the formatting stage. For example,

What is important here is to distinguish between data and representation. When you input an integer, you actually input a representation of the integer. That is, even without specifying the base, you don't enter the integer 42 (you would be hard-pressed to do that), but the decimal representation of the integer, consisting of the two digits 4 and 2, in that order, i.e. the string42. However Mathematica doesn't store it in that way; it would be impractical to do so. Instead it stores it in an internal, binary representation which matches the representation the processor uses for numbers. Finally when printing, it takes the internal representation and converts it to the decimal representaion, thus printing 42 again.

Now Mathematica allows you to input numbers in different representations, in your case, base 16 with a to f as extra digits. That is, if you type 16^^2a, Mathematica recognizes this as another representation of the same integer 42, and therefore also converts it into the internal representation of that integer. Then when displaying it, the printing code has no idea about where that integer it has to print comes from, you might have entered it in decimal form, in hexadecimal form, or you might not have entered it at all, but it might have been the result of a calculation like HitchHikerEvaluate[6 * 9]. All the printing routine knows is that here's an internal representation of the number 42 to print. And it does so by converting it into decimal, resulting in the output 42.

Note that conversion to internal form is not done by the evaluator. The evaluator takes an expression in internal form and evaluates that in order to get another expression in internal form. Conversion of input representation into internal representation, known as parsing, happens before the evaluation gets to see it, and it has to because the evaluator cannot act on the input, it only can act on the internal representation. Indeed, in your expression FullForm[16^^abcdef] it is the parsing which reveals that there's an expression with head FullForm and a single argument of type Integer. That is, at the time the expression exists (as result of parsing the input) the base already is gone.

Note that you can modify parsing as well. For the Front End, there's the Notation package which allows you to tell Mathematica how to interpret certain box structures you enter. And there's $PreRead which is applied to the input form before it is parsed. This way, it might be possible to change all base^^num expressions into some expression basenum[base, value] and implement arithmetics for that so that it acts mostly like an integer, except that it displays in base^^num form. Maybe an alternative would be to transform it into Interpretation["base^^num", value]. However I'm not sure how well that would work.

Mathematica is a registered trademark of Wolfram Research, Inc. While the mark is used herein with the limited permission of Wolfram Research, Stack Exchange and this site disclaim all affiliation therewith.