我已经写了代码:
int x = 18;
x *= 0.90;
System.out.println(x);
Run Code Online (Sandbox Code Playgroud)
这段代码打印出来16
然而,当我写下
int x = 18;
x = x * 0.90;
System.out.println(x);
Run Code Online (Sandbox Code Playgroud)
它给了我以下错误:incompatible types: possible lossy conversion from double to int
我预计这两个代码示例都会导致与 相同的错误x *= y;
,x = x * y;
但x *= 0.90;
不知何故有效,但x = x * 0.90;
无效。为什么会这样呢?
我正在解决一个我能够解决的问题,除了最后一块之外 - 我不知道如何使用按位运算符进行乘法运算:
0*8 = 0
1*8 = 8
2*8 = 16
3*8 = 24
4*8 = 32
Run Code Online (Sandbox Code Playgroud)
能否请您推荐一种方法来解决这个问题?
在C++中,说:
uint64_t i;
uint64_t j;
Run Code Online (Sandbox Code Playgroud)
然后i * j
将产生一个uint64_t
值为i
和之间的乘法的下半部分j
,即(i * j) mod 2^64
.现在,如果我想要乘法的较高部分怎么办?我知道在使用32位整数时,存在一个汇编指令做类似的事情,但我对汇编并不熟悉,所以我希望得到帮助.
制作以下内容的最有效方法是:
uint64_t k = mulhi(i, j);
Run Code Online (Sandbox Code Playgroud) 我正在编写需要快速乘以大数的数学代码.它分解为整数数组与单个整数的乘法.在C++中,这看起来像这样(在unsigned上):
void muladd(unsigned* r, const unsigned* a, unsigned len, unsigned b) {
unsigned __int64 of = 0; // overflow
unsigned i = 0; // loop variable
while (i < len) {
of += (unsigned __int64)a[i] * b + r[i];
r[i] = (unsigned)of;
of >>= 32;
++i;
}
r[i] = (unsigned)of; // save overflow
}
Run Code Online (Sandbox Code Playgroud)
我手动展开了这个循环,将其转换为64位并处理.asm编译器输出以进一步优化它.主.asm循环现在看起来像这样:
mov rax, rdi ; rdi = b
mul QWORD PTR [rbx+r10*8-64] ; rdx:rax = a[i] * b; r10 = i
mov rsi, QWORD PTR [r14+r10*8-64] …
Run Code Online (Sandbox Code Playgroud) (int)(33.46639 * 1000000)
回报 33466389
为什么会这样?
我正在寻找最方便的方法(double d
).到目前为止,我提出了两种方法:
1. d*d
2. Math.pow(d, 2)
Run Code Online (Sandbox Code Playgroud)
为了测试性能,我设置了三个测试用例,在每个测试用例中,我使用相同的种子为三种情况生成随机数,然后只计算循环100 000 000次的平方数.
在第一个测试案例中,使用random.nextDouble()
第二种情况下使用random.nextDouble()*Double.MAX_VALUE
和使用第三种 情况生成数字random.nextDouble()*Double.MIN_VALUE
.
几次运行的结果(近似结果,总是有一些变化,使用java 1.8运行,在Mac OSX Mavericks上为java 1.6编译)
Approach | Case 1 | Case 2 | Case 3
---------•--------•--------•-------
1 | ~2.16s | ~2.16s | ~2.16s
2 | ~9s | ~30s | ~60s
Run Code Online (Sandbox Code Playgroud)
结论似乎是方法1更快,但Math.pow
似乎表现得有些奇怪.
所以我有两个问题:
1为什么Math.pow
这么慢,为什么它会对数字造成严重影响> 1
甚至更糟< -1
?
2有没有办法提高性能超过我建议的方法1?我在考虑这样的事情:
long l = Double.doubleToRawLongBits(d);
long sign = (l & (1 << 63));
Double.longBitsToDouble((l<<1)&sign);
Run Code Online (Sandbox Code Playgroud)
但这是a)错误,和b)与方法1的速度相同.
我得到了这个C代码.
#include <stdio.h>
int main(void)
{
int n, d, i;
double t=0, k;
scanf("%d %d", &n, &d);
t = (1/100) * d;
k = n / 3;
printf("%.2lf\t%.2lf\n", t, k);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想知道为什么我的变量't'总是为零(在printf函数中)?
我已经写方案C++,Python和Java的矩阵乘法和测试他们的速度有两个2000×2000矩阵(见相乘后).标准的ikj-implementntation - 在 - 拿:
现在我已经实现了用于矩阵乘法的Strassen算法 - 它在 - 在维基百科上的Python和C++中.这些是我的时代:
为什么Strassen矩阵乘法比标准矩阵乘法慢得多?
这尤其令人惊讶,因为它似乎与其他人的经历相矛盾:
编辑:在我的情况下,Strassen矩阵乘法较慢的原因是:
strassen
和strassenRecursive
.第一个将矩阵的大小调整为2的幂,如果需要,称为第二个.但是strassenRecursive
没有递归地称呼自己,但是strassen
.long m = 24 * 60 * 60 * 1000 * 1000;
Run Code Online (Sandbox Code Playgroud)
上面的代码创建溢出并且不会打印正确的结果.
long m2 = 24L * 60 * 60 * 1000 * 1000;
long m3 = 24 * 60 * 60 * 1000 * 1000L;
Run Code Online (Sandbox Code Playgroud)
以上2行打印正确的结果.
我的问题是 -
m2
还是m3
?我想矢量化两个内存对齐数组的乘法.我没有找到任何方法在AVX/AVX2中乘以64*64位,所以我只是循环展开和AVX2加载/存储.有更快的方法吗?
注意:我不想保存每次乘法的高半结果.
void multiply_vex(long *Gi_vec, long q, long *Gj_vec){
int i;
__m256i data_j, data_i;
__uint64_t *ptr_J = (__uint64_t*)&data_j;
__uint64_t *ptr_I = (__uint64_t*)&data_i;
for (i=0; i<BASE_VEX_STOP; i+=4) {
data_i = _mm256_load_si256((__m256i*)&Gi_vec[i]);
data_j = _mm256_load_si256((__m256i*)&Gj_vec[i]);
ptr_I[0] -= ptr_J[0] * q;
ptr_I[1] -= ptr_J[1] * q;
ptr_I[2] -= ptr_J[2] * q;
ptr_I[3] -= ptr_J[3] * q;
_mm256_store_si256((__m256i*)&Gi_vec[i], data_i);
}
for (; i<BASE_DIMENSION; i++)
Gi_vec[i] -= Gj_vec[i] * q;
}
Run Code Online (Sandbox Code Playgroud)
更新:
我正在使用Haswell微体系结构和ICC/GCC编译器.所以AVX和AVX2都很好.我在乘法循环展开后-=
用C inrisic 替换_mm256_sub_epi64
它,在那里得到一些加速.目前,它是ptr_J[0] *= q; ...
我用, …