Let's look at the value stored in a1 converted to a uint64.
>> a1 = 9419588158802421600; b1 = 44;
>> a2 = uint64(9419588158802421600); b2 = uint64(44);
>> [uint64(a1); a2; intmax('uint64')]
3×1 uint64 column vector
Not all integer values on the magnitude of 9419588158802421600 can be exactly represented by a double. For example, the next representable number after a1 is:
>> uint64(a1 + eps(a1))
and the one immediately before it:
>> uint64(a1 - eps(a1)/2)
You can see this by looking at the hex representation of the numbers:
>> [a1 - eps(a1)/2; a1; a1 + eps(a1)]
They differ only in the last hex digit. So the computations in double and in uint64 are operating on different data. When you try to compute on numbers that are close to or greater than flintmax be very careful.