我正在尝试用4个复合字节构建一个32位浮点数.有没有比使用以下方法更好(或更便携)的方法?
#include <iostream>
typedef unsigned char uchar;
float bytesToFloat(uchar b0, uchar b1, uchar b2, uchar b3)
{
float output;
*((uchar*)(&output) + 3) = b0;
*((uchar*)(&output) + 2) = b1;
*((uchar*)(&output) + 1) = b2;
*((uchar*)(&output) + 0) = b3;
return output;
}
int main()
{
std::cout << bytesToFloat(0x3e, 0xaa, 0xaa, 0xab) << std::endl; // 1.0 / 3.0
std::cout << bytesToFloat(0x7f, 0x7f, 0xff, 0xff) << std::endl; // 3.4028234 × 10^38 (max single precision)
return 0;
}
Run Code Online (Sandbox Code Playgroud) 如果所有值都不超过一个或多个字节,并且没有字节可以包含元数据,那么系统如何跟踪字节所代表的数字类型?在维基百科上查看两个补码和单点揭示了这些数字如何用二进制表示,但我仍然想知道编译器或处理器(不确定我在这里处理的是什么)如何确定这个字节必须是有符号整数.
它类似于接收加密的信件,并且看着我的密码架,想知道要抓住哪一个.有些指标是必要的.
如果我想一下我可以做些什么来解决这个问题,我会想到两个解决方案.我要么声称一个额外的字节并用它来存储描述,要么我会专门为数值表示分配内存部分; 用于签名号码的部分,用于花车的部分等.
我主要在Unix系统上处理C,但这可能是一个更普遍的问题.
在CUDA C的一个项目中,我遇到了关于单精度和双精度浮点运算的意外行为.在项目中,我首先使用内核和另一个内核中的数字填充数组,然后对这些数字进行一些计算.所有变量和数组都是双精度的,所以我不希望任何单精度浮点运算发生.但是,如果我使用NVPROF分析程序的可执行文件,则表明执行了单精度操作.这怎么可能?
这是最小的程序,它在我的架构上显示了这种行为:(断言和错误捕获已被遗漏).我使用的是Nvidia Tesla k40显卡.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Nx 10
#define Ny 10
#define RANDOM double(0.236954587566)
__global__ void test(double *array, size_t pitch){
double rho, u;
int x = threadIdx.x + blockDim.x*blockIdx.x;
int y = threadIdx.y + blockDim.y*blockIdx.y;
int idx = y*(pitch/sizeof(double)) + 2*x;
if(x < Nx && y < Ny){
rho = array[idx];
u = array[idx+1]/rho;
array[idx] = rho*u;
}
}
__global__ void fill(double *array, size_t pitch){
int x = threadIdx.x + blockIdx.x * …Run Code Online (Sandbox Code Playgroud) 当您阅读MSDN时System.Single:
Single符合IEC 60559:1989(IEEE 754)二进制浮点运算标准.
和C#语言规范:
这些
float和double类型使用32位单精度和64位双精度IEEE 754格式表示[...]
然后:
根据IEEE 754算法的规则计算产品.
您很容易得到float类型及其乘法符合IEEE 754 的印象.
IEEE 754的一部分是多重定义.我的意思是,当你有两个float实例时,存在一个且只有一个float是他们的"正确"产品.不允许产品依赖于计算系统的某些"状态"或"设置".
现在,考虑以下简单程序:
using System;
static class Program
{
static void Main()
{
Console.WriteLine("Environment");
Console.WriteLine(Environment.Is64BitOperatingSystem);
Console.WriteLine(Environment.Is64BitProcess);
bool isDebug = false;
#if DEBUG
isDebug = true;
#endif
Console.WriteLine(isDebug);
Console.WriteLine();
float a, b, product, whole;
Console.WriteLine("case .58");
a = 0.58f;
b = 100f;
product = a * b;
whole = 58f;
Console.WriteLine(whole == …Run Code Online (Sandbox Code Playgroud) 我已经在 C 中实现了用单精度(32 位浮点)计算的三角函数(sin、cos、arctan)的一些近似值。它们精确到大约 +/- 2 ulp。
我的目标设备不支持任何<cmath>方法<math.h>。它不提供FMA,而是提供MAC ALU。ALU 和 LU 以 32 位格式进行计算。
我的反正切近似实际上是N.juffa 近似的修改版本,它在整个范围内近似反正切。正弦和余弦函数在 [-pi,pi] 范围内精确度高达 2 ulp。
我现在的目标是为正弦和余弦提供更大的输入范围(尽可能大,最好是 [FLT_MIN,FLT_MAX]),这使我能够减少参数。
我目前正在阅读不同的论文,例如KCNg 的 A RGUMENT REDUCTION FOR HUGE ARGUMENTS: Good to the Last Bit或有关此新参数缩减算法的论文,但我无法从中导出实现。
另外,我想提一下两个涉及相关问题的 stackoverflow 问题:有一种使用 matlab 和 c++ 的方法,它基于我链接的第一篇论文。它实际上使用 matlab、cmath 方法,并将输入限制为 [0,20.000]。另一种已经在评论中提到了。这是一种在 C 中实现 sin 和 cos 的方法,使用了我无法使用的各种 c 库。由于这两篇文章已经有几年的历史了,可能会有一些新的发现。
看起来这种情况下最常用的算法是将 2/pi 的数量精确存储到所需的位数,以便能够准确地进行模计算,同时避免取消。我的设备不提供大型 DMEM,这意味着无法查找具有数百位的大型查找表。该过程实际上在本参考文献的第 70 页上进行了描述,顺便说一句,它提供了许多有关浮点数学的有用信息。
所以我的问题是:是否有另一种有效的方法来减少正弦和余弦的参数以获得单精度,避免使用大的 LUT?上面提到的论文实际上专注于双精度并使用最多 1000 位数字,这不适合我的用例。
实际上我还没有找到任何 C 语言的实现,也没有找到针对单精度计算的实现,我将不胜感激任何类型的提示/链接/示例...
我目前正在研究余弦的近似值。由于最终目标设备是使用 32 位浮点 ALU / LU 的自行开发,并且有专门的 C 编译器,因此我无法使用 C 库数学函数(cosf,...)。我的目标是编写在准确性和指令/周期数量方面不同的各种方法。
我已经尝试了很多不同的近似算法,从 fdlibm、泰勒展开、pade 近似、使用枫树的 remez 算法等开始......
但是,一旦我仅使用浮点精度来实现它们,就会显着降低精度。并且可以肯定:我知道双精度,更高的精度完全没有问题......
现在,我有一些近似值,在 pi/2(出现最大误差的范围)附近精确到几千 ulp,我觉得我受到单精度转换的限制。
为了解决主题参数减少:输入是弧度。我认为参数减少会由于除法/乘法而导致更多的精度损失......因为我的整体输入范围只有 0..pi,我决定将参数减少到 0..pi/2。
因此,我的问题是:有没有人知道高精度(并且在最好的情况下效率高)余弦函数的单精度近似值?是否有任何算法可以优化单精度的近似值?你知道内置的 cosf 函数是否在内部计算单精度双精度的值吗?~
float ua_cos_v2(float x)
{
float output;
float myPi = 3.1415927410125732421875f;
if (x < 0) x = -x;
int quad = (int32_t)(x*0.63661977236f);//quad = x/(pi/2) = x*2/pi
if (x<1.58f && x> 1.57f) //exclude approximation around pi/2
{
output = -(x - 1.57079637050628662109375f) - 2.0e-12f*(x - 1.57079637050628662109375f)*(x - 1.57079637050628662109375f) + 0.16666667163372039794921875f*(x - 1.57079637050628662109375f)*(x - 1.57079637050628662109375f)*(x - 1.57079637050628662109375f) …Run Code Online (Sandbox Code Playgroud) c floating-point trigonometry approximation single-precision
我正在玩浮点运算,我遇到了需要解释的东西.
将舍入模式设置为"朝零"时,又称:
fesetround(FE_TOWARDZERO);
Run Code Online (Sandbox Code Playgroud)
并且添加不同类型的正常正数,我永远无法达到Infinity.
然而,从ieee 745可知,向无穷大的溢出可以通过添加有限数来产生.
例如:
#include <fenv.h>
#include <stdio.h>
float hex2float (int hex_num) {
return *(float*)&hex_num;
}
void main() {
int a_int = 0x7f7fffff; // Maximum finite single precision number, about 3.4E38
int b_int = 0x7f7fffff;
float a = hex2float(a_int);
float b = hex2float(b_int);
float res_add;
fesetround(FE_TOWARDZERO); // need to include fenv.h for that
printf("Calculating... %+e + %+e\n",a,b);
res_add = a + b;
printf("Res = %+e\n",res_add);
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我将舍入模式更改为其他模式,我可能会得到+ INF作为答案.
有人可以解释一下吗?
根据几个浮点计算器以及我下面的代码,以下 32 位00111111010000000100000110001001的实际浮点值为 (0.750999987125396728515625)。由于它是实际的 Float 值,我应该认为将它存储在 Double 或 Float 中将保留精度和精确值,只要 (1) 不执行算术 (2) 使用实际值和 (3) 值是没有被贬低。那么为什么实际值与 (0.7509999871253967) 的强制转换(示例 1)和文字(示例 2)值不同?
我以这个计算器为例:https : //www.h-schmidt.net/FloatConverter/IEEE754.html
import java.math.BigInteger;
import java.math.BigDecimal;
public class MyClass {
public static void main(String args[]) {
int myInteger = new BigInteger("00111111010000000100000110001001", 2).intValue();
Double myDouble = (double) Float.intBitsToFloat(myInteger);
String myBidDecimal = new BigDecimal(myDouble).toPlainString();
System.out.println(" bits converted to integer: 00111111010000000100000110001001 = " + myInteger);
System.out.println(" integer converted to double: " + myDouble);
System.out.println(" double converted to BigDecimal: " …Run Code Online (Sandbox Code Playgroud) 我需要读取文件的二进制内容并将提取的字节转换为单精度浮点数。如何做到这一点已经在这里被问过。这个问题确实有正确的答案,但我想知道特定的答案是否实际上是有效的 C++ 代码。
该答案给出了以下代码:
float bytesToFloat(uint8_t *bytes, bool big_endian) {
float f;
uint8_t *f_ptr = (uint8_t *) &f;
if (big_endian) {
f_ptr[3] = bytes[0];
f_ptr[2] = bytes[1];
f_ptr[1] = bytes[2];
f_ptr[0] = bytes[3];
} else {
f_ptr[3] = bytes[3];
f_ptr[2] = bytes[2];
f_ptr[1] = bytes[1];
f_ptr[0] = bytes[0];
}
return f;
}
Run Code Online (Sandbox Code Playgroud)
这实际上是有效的 C++ 代码吗?我不确定它是否违反任何别名规则。
请注意,我的目标平台是大端字节序,其中浮点数保证至少为 32 位长。
c++ floating-point endianness language-lawyer single-precision
我有兴趣学习如何使用按位运算符将整数值转换为IEEE单精度浮点格式.但是,我很困惑在计算指数时可以做些什么来知道剩下多少逻辑位移.
给定一个int,比如15,我们有:
二进制:1111
- > 1.111 x 2 ^ 3 =>在第一位后面放置一个小数点后,我们发现'e'值为3.
E = Exp - 偏差因此,Exp = 130 = 10000010
并且有效数将是:111000000000000000000000
但是,我知道'e'值将是3,因为我能够看到在第一位之后放置小数后有三位.作为一般情况,是否有更通用的代码编码方式?
同样,这是针对int到float的转换,假设整数是非负的,非零,并且不大于尾数允许的最大空间.
此外,有人可以解释为什么大于23位的值需要舍入?提前致谢!
single-precision ×10
c ×4
c++ ×3
endianness ×2
ieee-754 ×2
precision ×2
64-bit ×1
assembly ×1
bigdecimal ×1
c# ×1
clr ×1
cuda ×1
int ×1
java ×1
memory ×1
portability ×1
trigonometry ×1