在Haskell中,base库和Hackage包提供了几种将二进制IEEE-754浮点数据转换为提升Float和Double类型的方法.但是,这些方法的准确性,性能和可移植性尚不清楚.
对于旨在(跨)平台(反)序列化二进制格式的GHC目标库,处理IEEE-754浮点数据的最佳方法是什么?
这些是我在现有库和在线资源中遇到的方法.
这是data-binary-ieee754包使用的方法.因为Float,Double,Word32和Word64是的每个实例Storable中,一个能poke源类型的值到外部缓冲器,然后peek目标类型的一个值:
toFloat :: (F.Storable word, F.Storable float) => word -> float
toFloat word = F.unsafePerformIO $ F.alloca $ \buf -> do
F.poke (F.castPtr buf) word
F.peek buf
Run Code Online (Sandbox Code Playgroud)
在我的机器上这是有效的,但我畏缩看到分配只是为了完成强制.此外,虽然这个解决方案并不是唯一的,但这里隐含的假设是IEEE-754实际上是内存中的表示.包装附带的测试给它"在我的机器上工作"的批准印章,但这并不理想.
unsafeCoerce使用内存中IEEE-754表示的相同隐含假设,以下代码也可以获得"在我的机器上工作"的封条:
toFloat :: Word32 -> Float
toFloat = unsafeCoerce
Run Code Online (Sandbox Code Playgroud)
这样做的好处是不像上面的方法那样执行显式分配,但是文档说"你有责任确保旧的和新的类型具有相同的内部表示".这个隐含的假设仍然在做所有的工作,在处理提升的类型时更加费劲.
unsafeCoerce#扩展可能被视为"便携"的限制:
toFloat :: Word -> Float
toFloat (W# w) …Run Code Online (Sandbox Code Playgroud) 我需要一个跨平台的库/算法,它将在32位和16位浮点数之间进行转换.我不需要使用16位数进行数学运算; 我只需要减小32位浮点数的大小,以便它们可以通过网络发送.我在C++工作.
我理解我会失去多少精确度,但这对我的应用来说是可以的.
IEEE 16位格式会很棒.
根据我的阅读,数据类型double的值具有小数点后15位的近似精度.但是,当我使用其十进制表示重复的数字,例如1.0/7.0时,我发现变量保持值为0.14285714285714285 - 这是17位(通过调试器).
我想知道为什么它在内部表示为17个位置,为什么15的精度始终写在〜15?
对于类型T为其中std::is_floating_point<T>::value的true,不C++标准规定上的任何方式T应实施?
例如,是否T甚至遵循符号/尾数/指数表示?或者它可以是完全随意的?
我尝试了两种不同的方法来在Java中找到平方根:
Math.sqrt(Double.NEGATIVE_INFINITY); // NaN
Math.pow(Double.NEGATIVE_INFINITY, 0.5); // Infinity
Run Code Online (Sandbox Code Playgroud)
为什么第二种方式不能返回预期的答案NaN(与第一种方式相同)?
我已经看过很长的文章,解释了如何存储浮点数以及这些数字的算法是如何完成的,但请简要说明为什么我写的时候
cout << 1.0 / 3.0 <<endl;
Run Code Online (Sandbox Code Playgroud)
我看到0.333333,但是当我写的时候
cout << 1.0 / 3.0 + 1.0 / 3.0 + 1.0 / 3.0 << endl;
Run Code Online (Sandbox Code Playgroud)
我明白了1.
电脑如何做到这一点?请解释这个简单的例子.这对我来说已经足够了.
假设符合IEEE-754标准,是否保证在通过双重传输时保留浮动?
换句话说,以下断言是否会始终满足?
int main()
{
float f = some_random_float();
assert(f == (float)(double)f);
}
Run Code Online (Sandbox Code Playgroud)
假设f可以获取IEEE定义的任何特殊值,例如NaN和Infinity.
根据IEEE的说法,是否存在断言将被满足的情况,但是在通过double传输之后不能保留确切的位级表示?
代码段在C和C++中都有效.
两个以下有什么区别?
float f1 = some_number;
float f2 = some_near_zero_number;
float result;
result = f1 / f2;
Run Code Online (Sandbox Code Playgroud)
和:
float f1 = some_number;
float f2 = some_near_zero_number;
float result;
result = (double)f1 / (double)f2;
Run Code Online (Sandbox Code Playgroud)
我对非常小的f2值特别感兴趣,这些值在浮点运算时可能产生+无穷大.是否有任何准确性?
使用这种演员表的一些实用指南也会很好.
当我在32位和64位环境下运行我的应用程序时双倍大小有什么区别吗?
如果我没有弄错的话,32位环境中的双精度将在0之后占用16位数,而64位中的双位将占用32位,我是对的吗?
我正在读一本C书,谈论浮点范围,作者给出了表:
Type Smallest Positive Value Largest value Precision
==== ======================= ============= =========
float 1.17549 x 10^-38 3.40282 x 10^38 6 digits
double 2.22507 x 10^-308 1.79769 x 10^308 15 digits
Run Code Online (Sandbox Code Playgroud)
我不知道最小正值和最大值列中的数字来自哪里.