It's writing exactly what you tell it to, 4 bytes at the address of d (an integer, 32 bit on many platforms). Use a 16 bit type and write 2 bytes instead:
uint16_t d; // unsigned to ensure it's large enough to hold your max value of 46000
while (in >> d) out.write(reinterpret_cast<char*>(&d), sizeof d);
Edit: As pointed out in the comments, for this code and the data it generates to be portable across processor architectures you should pick an endianness convention for the output. I'd suggest using htons() to convert your uint16_t to network byte order which is widely available, though not (yet) part of the C++ standard.