我最近选择了Bruce Schneier的应用密码学副本,这是一本很好的阅读.我现在明白本书中概述的几种算法是如何工作的,我想在C中开始实现其中的一些算法.
许多算法的共同点是将x位密钥分成几个较小的y位密钥.例如,Blowfish的密钥X是64位,但是你需要将它分成两个32位的一半; Xl和Xr.
这是我陷入困境的地方.我对C相当不错,但对于按位运算符等,我并不是最强的.
在获得IRC的一些帮助后,我设法提出了这两个宏:
#define splitup(a, b, c) {b = a >> 32; c = a & 0xffffffff; }
#define combine(a, b, c) {a = (c << 32) | a;}
Run Code Online (Sandbox Code Playgroud)
其中a是64位,b和c是32位.但是,编译器警告我,我正在将32位变量移位32位.
我的问题是这些:
正如我所说的,我对C非常熟悉,但是按位操作符等仍让我头疼.
编辑
我发现我的组合宏实际上并没有组合两个32位变量,而只是简单地将0和0相加,并得到一个结果.
所以,除了我以前的问题,我仍然没有一种方法将两个32位变量组合起来得到一个64位变量; 关于如何做到这一点的建议将不胜感激.
我正在尝试快速的Exp(x)函数,这个函数之前在这个回答中描述了一个提高C#计算速度的SO问题:
public static double Exp(double x)
{
var tmp = (long)(1512775 * x + 1072632447);
return BitConverter.Int64BitsToDouble(tmp << 32);
}
Run Code Online (Sandbox Code Playgroud)
表达式使用一些IEEE浮点"技巧",主要用于神经集.该功能比常规Math.Exp(x)
功能快约5倍.
不幸的是,相对于常规Math.Exp(x)
函数,数值精度仅为-4% - + 2%,理想情况下,我希望精度至少在亚百分比范围内.
我已经绘制了近似和常规Exp函数之间的商,并且从图中可以看出,相对差异似乎以几乎恒定的频率重复.
是否有可能利用这种规律性来进一步提高"快速exp"功能的准确性而不会显着降低计算速度,或者精度提高的计算开销是否会超过原始表达式的计算增益?
(作为旁注,我也尝试过在同一个SO问题中提出的替代方法之一,但这种方法在C#中似乎没有计算效率,至少在一般情况下并非如此.)
5月14日更新
根据@Adriano的要求,我现在已经执行了一个非常简单的基准测试.我已经使用每个替代exp函数对[-100,100]范围内的浮点值执行了1000万次计算.由于我感兴趣的值范围从-20到0,我还明确列出了x = -5处的函数值.结果如下:
Math.Exp: 62.525 ms, exp(-5) = 0.00673794699908547
Empty function: 13.769 ms
ExpNeural: 14.867 ms, exp(-5) = 0.00675211846828461
ExpSeries8: 15.121 ms, exp(-5) = 0.00641270968867667
ExpSeries16: 32.046 ms, exp(-5) = 0.00673666189488182
exp1: 15.062 ms, exp(-5) = -12.3333325982094
exp2: 15.090 …
Run Code Online (Sandbox Code Playgroud) 我一直在努力寻找一种可移植的方法来序列化C和C++中的32位浮点变量,以便发送到微控制器和从微控制器发送.我希望格式足够明确,以便可以从其他语言完成序列化/反序列化,而无需太多努力.相关问题是:
我知道在大多数情况下,类型转换联合/ memcpy可以正常工作,因为浮动表示是相同的,但我宁愿有更多的控制和心灵.到目前为止我想出的是以下内容:
void serialize_float32(uint8_t* buffer, float number, int32_t *index) {
int e = 0;
float sig = frexpf(number, &e);
float sig_abs = fabsf(sig);
uint32_t sig_i = 0;
if (sig_abs >= 0.5) {
sig_i = (uint32_t)((sig_abs - 0.5f) * 2.0f * 8388608.0f);
e += 126;
}
uint32_t res = ((e & 0xFF) << 23) | (sig_i & 0x7FFFFF);
if (sig < 0) {
res |= 1 << 31;
}
buffer[(*index)++] = (res …
Run Code Online (Sandbox Code Playgroud) 我有一个unsigned long long
(或uint64_t
)值,并希望将其转换为double
.double应具有与该long
值相同的位模式.这样我就可以"手动"设置双重位.
unsigned long long bits = 1ULL;
double result = /* some magic here */ bits;
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种方法来做到这一点.
c ×2
c++ ×2
32bit-64bit ×1
c# ×1
double ×1
embedded ×1
exp ×1
gcc ×1
long-integer ×1
performance ×1