我正在 Arduino 上编写一些代码,该代码需要快速运行并对整数百分比进行粗略近似。
例如,给定一个数字,我想找到它的 90%、70% 或 30% 等。最明显的方法是乘以浮点,例如。x * 0.9;或 x * 0.3;但因为我需要速度,所以我想避免浮点计算。如果我只是除以 2 的幂,我会进行按位移位,但是是否有类似的技术可以使用整数来近似 90%、80% 等?
performance heuristics arduino integer-division integer-arithmetic
我正在阅读关于C的教程,我遇到了这种语法:
int doses[] = {1, 3, 2, 1000};
doses[3] == *(doses + 3) == *(3 + doses) == 3[doses]
Run Code Online (Sandbox Code Playgroud)
现在重点是获得int 1000,但最后一个没有任何意义.要么它的晚期和我的大脑没有运作,它的特定于C的东西,或它的错字.我想在指针上涵盖我所有的基础知识,仔细阅读它.这意味着要理解这一切.任何答案将不胜感激!
据报道,Java 8具有对无符号整数的库支持.但是,似乎没有文章解释如何使用它以及可能的程度.
像Integer.CompareUnsigned这样的函数很容易找到并且似乎可以达到预期的效果.但是,我甚至没有编写一个简单的循环,它在无符号长整数范围内循环遍历2的所有幂.
int i = 0;
for(long l=1; (Long.compareUnsigned(l, Long.MAX_VALUE*2) < 0) && i<100; l+=l) {
System.out.println(l);
i++;
}
Run Code Online (Sandbox Code Playgroud)
产生输出
1
2
4
8
...
1152921504606846976
2305843009213693952
4611686018427387904
-9223372036854775808
0
0
0
...
0
Run Code Online (Sandbox Code Playgroud)
我是否遗漏了一些东西,或者这个简单的任务仍然需要外部库?
在执行带有溢出检查的整数算术时,计算通常需要组合多个算术运算。在 Rust 中链接检查算术的一种直接方法是使用checked_*方法和Option链接:
fn calculate_size(elem_size: usize,
length: usize,
offset: usize)
-> Option<usize> {
elem_size.checked_mul(length)
.and_then(|acc| acc.checked_add(offset))
}
Run Code Online (Sandbox Code Playgroud)
但是,这告诉编译器为每个基本操作生成一个分支。我遇到了一种使用overflowing_*方法更展开的方法:
fn calculate_size(elem_size: usize,
length: usize,
offset: usize)
-> Option<usize> {
let (acc, oflo1) = elem_size.overflowing_mul(length);
let (acc, oflo2) = acc.overflowing_add(offset);
if oflo1 | oflo2 {
None
} else {
Some(acc)
}
}
Run Code Online (Sandbox Code Playgroud)
不考虑溢出而继续计算并使用按位 OR 聚合溢出标志可确保在整个评估中最多执行一个分支(前提是overflowing_*生成无分支代码的实现)。这种优化友好的方法更麻烦,并且在处理中间值时需要谨慎。
有没有人有过 Rust 编译器如何在各种 CPU 架构上优化上述任一模式的经验,以判断显式展开是否值得,尤其是对于更复杂的表达式?
我正在使用Gforth,我寻找一个标准的Forth字来划分两个双整数,或者至少是一个双整数的混合除以一个整数,但结果支持双整数.似乎没有一个.SM/REM,FM/MOD并UM/MOD有所有限制.
我错过了什么吗?为什么这个词不会与Forth内置?该操作定义明确,不会发生算术溢出.是否有必要自己编程?
我正在尝试为Rust u32和u64数据类型实现快速素性测试.作为它的一部分,我需要计算(n*n)%d其中n和d是u32(或u64,分别地).
虽然结果很容易适合数据类型,但我对如何计算它感到茫然.据我所知,没有处理器原语.
因为u32我们可以伪造它 - 铸造u64,以便产品不会溢出,然后取模数,然后再回落u32,知道这不会溢出.但是因为我没有u128数据类型(据我所知),这个技巧不起作用u64.
因此,对u64,我能想到的最明显的方式来完成,这是莫名其妙地计算x*y得到一对(carry, product)的u64,所以我们捕获,而不是仅仅失去它(或恐慌,或其他)溢出量.
有没有办法做到这一点?还是另一种解决问题的标准方法?
我的问题仅限于 256 位无符号整数。
我有一个值x,我需要按比率对其进行除垢n / d,其中n < d。
简单的解决方案当然是x * n / d,但问题是x * n可能会溢出。
我正在寻找任何可能有助于获得尽可能准确的结果的算术技巧。
在计算之前将每个 和 除以n并d不能保证成功。gcd(n, d)x * n / d
我可以使用任何流程(迭代或其他)来解决这个问题吗?
请注意,我愿意选择不准确的解决方案,但我需要能够估计错误。
有一个相对知名的技巧可以取消设置最右边的一个位:
y = x & (x - 1) // 0b001011100 & 0b001011011 = 0b001011000 :)
Run Code Online (Sandbox Code Playgroud)
我发现自己有一个紧密的循环来清除最右边的 n 位,但是有更简单的代数技巧吗?
假设 n 相对较大(对于 64 位整数,n 必须小于 64,但通常约为 20-30)。
// x = 0b001011100 n=2
for (auto i=0; i<n; i++) x &= x - 1;
// x = 0b001010000
Run Code Online (Sandbox Code Playgroud)
我翻阅了 TAOCP Vol4 几次,但找不到任何灵感。
也许有一些硬件支持?
我想知道 x**2 还是 x*x 更快
def sqr(x):
for i in range (20):
x = x**2
return x
def sqr_(x):
for i in range (20):
x = x*x
return x
Run Code Online (Sandbox Code Playgroud)
当我计时时,这就是我得到的:
The time it takes for x**2: 101230500
The time it takes for x*x: 201469200
Run Code Online (Sandbox Code Playgroud)
我已经尝试了很多很多次,它们要么相等,要么 x ** 2 比 x * x 快。但 x*x 永远不会比 x**2 快。
所以我反驳了代码:
对于 x**2:
5 12 LOAD_FAST 0 (x)
14 LOAD_CONST 2 (2)
16 BINARY_POWER
18 STORE_FAST 0 (x)
20 JUMP_ABSOLUTE 8
Run Code Online (Sandbox Code Playgroud)
对于 x*x: …
以下程序:
#include <iostream>
#include <string>
int main ()
{
unsigned char result1 {0};
unsigned char result2 {0};
result1 = (result1 - 1) % 8;
result2 = result2 - 1;
result2 = result2 % 8;
std::cout << "result1 is " << std::to_string (result1) << '\n';
std::cout << "result2 is " << std::to_string (result2) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
result1 is 255
result2 is 7
Run Code Online (Sandbox Code Playgroud)
为什么result1和result2的计算结果不同?
我尝试了几个编译器,但它们都产生相同的结果,所以这一定是我不明白的地方。