从 4 字节 char 数组到 int 的精度损失?
loss of precision from 4 byte char array to int?
我正在尝试从 /dev/random 中提取整数值的数据。下面的代码有效。我想了解的是为什么我必须对最终输出使用 size_t 类型以避免精度损失。查看代码中的注释。
我认为问题可能是 .read 方法添加了某种类型的填充,例如空终止字符,我尝试将长度设置为 3 以避免出现这种情况,但这似乎并不重要。我很高兴知道如何解决这个问题,但我想了解为什么我必须这样做。
size_t getSeed()
{
std::ifstream rnd ("/dev/random", std::ios::binary);
if( rnd.is_open() )
{
int len = sizeof(int); // 4 bytes
char* blk = new char [len];
rnd.read ( blk, len ); // 8 bytes?
rnd.close();
size_t out = (size_t)*blk; // loss of precision with int
delete[] blk;
return out;
}
else
{
return 0;
}
}
我不明白你为什么以二进制模式读取 4 char
然后将它们保存到 int
,即 size_t
。直接从流读取到 size_t out
会更容易:
size_t out;
rnd.read ( &out, sizeof(out) );
但是,如果这只是一个实验,我想向您推荐一些变体,将 4 个字符打包成一个 32 位整数。
第一个(C 风格)选项 union
:
#include <cstdint>
union ConversionUnion
{
int32_t dint;
char dchar[4];
};
int32_t getSeed()
{
std::ifstream rnds ("/dev/random", std::ios::binary);
ConversionUnion conv;
if( rnds.is_open() )
{
rnds.read (conv.dchar, sizeof(int32_t ));
rnds.close();
return conv.dint;
}
else
{
return 0;
}
}
如果您只想修复代码,请尝试更改行
size_t out = (size_t)*blk;
到行(这也是 C 而不是 C++)
size_t out = *((size_t*)blk);
同时考虑用于 4 个数字(不是数组)的解决方案 - here。但是同样的方法可以用于数组:
int32_t result = 0;
for(int i = 0; i < 4; i++) // or
// for(int i = 3; i > 0; i--) // for reverse order of bytes if needed
{
result <<= 8;
result |= blk[i];
}
我正在尝试从 /dev/random 中提取整数值的数据。下面的代码有效。我想了解的是为什么我必须对最终输出使用 size_t 类型以避免精度损失。查看代码中的注释。
我认为问题可能是 .read 方法添加了某种类型的填充,例如空终止字符,我尝试将长度设置为 3 以避免出现这种情况,但这似乎并不重要。我很高兴知道如何解决这个问题,但我想了解为什么我必须这样做。
size_t getSeed()
{
std::ifstream rnd ("/dev/random", std::ios::binary);
if( rnd.is_open() )
{
int len = sizeof(int); // 4 bytes
char* blk = new char [len];
rnd.read ( blk, len ); // 8 bytes?
rnd.close();
size_t out = (size_t)*blk; // loss of precision with int
delete[] blk;
return out;
}
else
{
return 0;
}
}
我不明白你为什么以二进制模式读取 4 char
然后将它们保存到 int
,即 size_t
。直接从流读取到 size_t out
会更容易:
size_t out;
rnd.read ( &out, sizeof(out) );
但是,如果这只是一个实验,我想向您推荐一些变体,将 4 个字符打包成一个 32 位整数。
第一个(C 风格)选项 union
:
#include <cstdint>
union ConversionUnion
{
int32_t dint;
char dchar[4];
};
int32_t getSeed()
{
std::ifstream rnds ("/dev/random", std::ios::binary);
ConversionUnion conv;
if( rnds.is_open() )
{
rnds.read (conv.dchar, sizeof(int32_t ));
rnds.close();
return conv.dint;
}
else
{
return 0;
}
}
如果您只想修复代码,请尝试更改行
size_t out = (size_t)*blk;
到行(这也是 C 而不是 C++)
size_t out = *((size_t*)blk);
同时考虑用于 4 个数字(不是数组)的解决方案 - here。但是同样的方法可以用于数组:
int32_t result = 0;
for(int i = 0; i < 4; i++) // or
// for(int i = 3; i > 0; i--) // for reverse order of bytes if needed
{
result <<= 8;
result |= blk[i];
}