无法对unsigned long十六进制数据移位,IEEE754转十进制遇0值求助
Let's break down why your code is returning 0 and resolve the issues step by step:
Core Problems in Your Code
Mismatched Data Type for 64-bit Values
unsigned longis typically a 32-bit type on most systems (including Eclipse's default targets). IEEE 754 double-precision requires 64 bits to store the full mantissa, exponent, and sign. Using a 32-bit type truncates your 8-byte raw data, leading to loss of critical bits needed for accurate conversion.Invalid Bit Shift Operations
Shifting by512,256, etc., is undefined behavior for 32/64-bit types—these values are way larger than the number of bits in the type. For a 32-bitunsigned long, shifts are modulo 32, so<<512is equivalent to<<0(no shift at all). This is why you only seeCCCCCDwhen printingstrData: all higher bytes are effectively ignored, leaving only the last 3 bytes of your intended 8-byte value.Truncated 64-bit Constants
The double-precision exponent mask0x7FF0000000000000is a 64-bit constant, but storing it in anunsigned long(32-bit) truncates it to 0. This makes your exponent calculation completely invalid.
Step-by-Step Fixes
1. Switch to 64-bit Unsigned Integers
Replace unsigned long with uint64_t (from <stdint.h>) or unsigned long long to handle the full 64-bit IEEE 754 double-precision data without truncation.
2. Correct Bit Shift Calculations
For 8-byte (64-bit) data, each byte should be shifted by multiples of 8 (not 512/256). Assuming your raw data is in big-endian order (where strResponseData[12] is the highest-order byte of the double-precision value), here's how to assemble the 64-bit value correctly:
#include <stdint.h> // Initialize your raw response data (matching your provided hex values) char strResponseData[STATUS_BUFFERSIZE] = {0x7E, 0xFF, 0x01, 0x46, 0x4B, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x10, 0x40, 0x1B, 0x7E}; uint64_t strData = ((uint64_t)(strResponseData[12] & 0xFF) << 56) | ((uint64_t)(strResponseData[11] & 0xFF) << 48) | ((uint64_t)(strResponseData[10] & 0xFF) << 40) | ((uint64_t)(strResponseData[9] & 0xFF) << 32) | ((uint64_t)(strResponseData[8] & 0xFF) << 24) | ((uint64_t)(strResponseData[7] & 0xFF) << 16) | ((uint64_t)(strResponseData[6] & 0xFF) << 8) | ((uint64_t)(strResponseData[5] & 0xFF) << 0);
Note: Cast each byte to uint64_t before shifting to avoid 32-bit overflow during the operation.
3. Update the Conversion Function
Modify the function to accept a 64-bit parameter and use matching 64-bit masks:
#include <math.h> double IEEEHexToDec(uint64_t number, int isDoublePrecision) { int mantissaShift = isDoublePrecision ? 52 : 23; uint64_t exponentMask = isDoublePrecision ? 0x7FF0000000000000ULL : 0x7F800000U; int bias = isDoublePrecision ? 1023 : 127; int signShift = isDoublePrecision ? 63 : 31; // Extract sign bit int sign = (number >> signShift) & 0x01; // Calculate exponent (adjusted for IEEE 754 bias) int exponent = ((number & exponentMask) >> mantissaShift) - bias; // Calculate mantissa value (sum of fractional bits) double total = 0.0; for (int i = 0; i < mantissaShift; i++) { int bit = (number >> (mantissaShift - i - 1)) & 0x01; total += bit * pow(2.0, -(i + 1)); } // Compute final floating-point value double value = (sign ? -1.0 : 1.0) * pow(2.0, exponent) * (1.0 + total); return value; }
4. (Optional) Simplify with Memory Copy
If you're confident the byte order of your raw data matches your system's native byte order, you can skip manual bit shifting entirely and copy the 8 bytes directly into a double:
double value; // Copy 8 bytes starting at index 5 into the double variable memcpy(&value, &strResponseData[5], sizeof(double));
Note: If your device uses a different byte order (e.g., big-endian vs. little-endian) than your system, you'll need to swap bytes first to get the correct value.
Why Your Original Code Returned 0
The truncated strData (only 0xCDCCCD from the last 3 bytes) resulted in a 32-bit value where all high bits (including the double-precision exponent bits) were 0. This made the exponent calculation 0 - 1023 = -1023, and 2^-1023 is an extremely small value—effectively zero for practical purposes.
内容的提问来源于stack exchange,提问作者maniwal rohit

