You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python写入np.float64二进制文件,C++以char读零值为何非零?

问题:Python写入的np.float64二进制文件,C++以char读取时零值显示非零的原因

我用Python生成np.float64类型的数据并写入二进制文件,用C++读取时,以double格式能得到原始数据,但以char格式读取时,原数据中的零值却显示大量非零值。这是什么原因?操作有误吗?


Python写入代码(原版本)

import numpy as np
a = np.array([1,3,4,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,4,3,1], dtype=np.float64)
with open("temp.txt", "wb") as binary_file:
    # Write bytes to file
    for values in a:
       binary_file.write(values)

C++读取代码(原版本)

#include <fstream>
#include <iterator>
#include <iostream>
#include "compression.h"
#include <vector>
#include <iomanip>
#include <chrono>
using namespace std;
int main(int argc, char ** argv)
{
    if (argc != 2) {
        std::cerr << "Need filename" << std::endl;
        return -1;
    }
    
    // enable check against decompress
    bool CHECK_ERR = true;
    std::string file(argv[1]);
    std::ifstream input(file, std::ios::in | std::ios::binary | std::ios::ate);
    std::streampos size;
    size = input.tellg();
    input.seekg(0, std::ios::beg);
      
    // Reading data as double 
    std::vector<double> fileData(size/sizeof(double));
    input.read((char*) &fileData[0], size);
    // This will generate the correct values, which I need
    for (int i=0; i<fileData.size(); i++ )
     cout<< fileData.at(i)<<" ";
    cout << endl;
    
    // Reading data in character format
    std::ifstream inputChr(file, std::ios::in | std::ios::binary | std::ios::ate);
   inputChr.seekg(0, std::ios::beg);
    while(size >= 64)
    {
      char memblock[64];
      inputChr.read((char*) &memblock, 64);
      cout << "Character values "<< endl;
      for (int i=0; i<64; i++)
          cout  << +(memblock[i]) << "  ";
      cout << endl;
      size--;
    }
return 0;
}

原因分析与解决方案

1. Python写入代码的核心错误

binary_file.write(values)的写法是无效的,file.write()要求传入字节对象,而直接传入np.float64标量会触发类型错误。错误的写入方式会导致文件内容并非正确的double二进制表示,这是读取异常的根源之一。

正确的写入方式应该将numpy标量转换为字节流,或者直接写入整个数组:

import numpy as np
a = np.array([1,3,4,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,4,3,1], dtype=np.float64)
with open("temp.bin", "wb") as binary_file:
    # 高效写法:一次性写入整个数组的字节流
    a.tofile(binary_file)
    # 或循环写入每个元素:
    # for val in a:
    #     binary_file.write(val.tobytes())

2. C++读取代码的循环逻辑错误

原代码中size--的逻辑完全错误:每次读取64字节后,剩余字节数应该减去64,而非1。当前逻辑会导致循环执行数百次,反复读取文件内容,甚至读取文件末尾外的操作系统垃圾数据,这些垃圾值就是你看到的“非零值”。

修正后的C++读取逻辑:

#include <fstream>
#include <iterator>
#include <iostream>
#include "compression.h"
#include <vector>
#include <iomanip>
#include <chrono>
using namespace std;
int main(int argc, char ** argv)
{
    if (argc != 2) {
        std::cerr << "Need filename" << std::endl;
        return -1;
    }
    
    bool CHECK_ERR = true;
    std::string file(argv[1]);
    std::ifstream input(file, std::ios::in | std::ios::binary | std::ios::ate);
    std::streampos totalSize = input.tellg();
    input.seekg(0, std::ios::beg);
      
    // 以double读取(原逻辑正确,保留)
    std::vector<double> fileData(totalSize/sizeof(double));
    input.read(reinterpret_cast<char*>(&fileData[0]), totalSize);
    for (double val : fileData)
        cout << val << " ";
    cout << endl;
    
    // 以char读取,修正循环逻辑
    std::ifstream inputChr(file, std::ios::in | std::ios::binary);
    std::streampos remainingSize = totalSize;
    inputChr.seekg(0, std::ios::beg);
    
    while(remainingSize >= 64)
    {
        char memblock[64];
        inputChr.read(memblock, 64);
        cout << "Character values:" << endl;
        for (int i=0; i<64; i++)
            cout << +static_cast<signed char>(memblock[i]) << "  ";
        cout << endl;
        remainingSize -= 64;
    }
    
    // 处理剩余不足64字节的部分
    if (remainingSize > 0)
    {
        char memblock[64];
        inputChr.read(memblock, remainingSize);
        cout << "Remaining character values:" << endl;
        for (int i=0; i<remainingSize; i++)
            cout << +static_cast<signed char>(memblock[i]) << "  ";
        cout << endl;
    }
    return 0;
}

3. 浮点数二进制存储的补充说明

np.float64对应C++的double类型,占8字节。IEEE 754标准中,数值0.0的double二进制表示是全8字节0,修正代码后,以char读取零值时会显示连续8个0,符合预期。


内容的提问来源于stack exchange,提问作者nivedita

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 13:54:57