相关疑难解决方法(0)

平均3个长整数

我有3个非常大的有符号整数.

long x = long.MaxValue;
long y = long.MaxValue - 1;
long z = long.MaxValue - 2;
Run Code Online (Sandbox Code Playgroud)

我想计算他们的截断平均值.预期的平均值是long.MaxValue - 1,即9223372036854775806.

无法将其计算为:

long avg = (x + y + z) / 3; // 3074457345618258600
Run Code Online (Sandbox Code Playgroud)

注意:我阅读了有关2个数字的平均值的所有问题,但我不知道该技术如何应用​​于平均3个数字.

使用它会很容易BigInteger,但我们假设我不能使用它.

BigInteger bx = new BigInteger(x);
BigInteger by = new BigInteger(y);
BigInteger bz = new BigInteger(z);
BigInteger bavg = (bx + by + bz) / 3; // 9223372036854775806
Run Code Online (Sandbox Code Playgroud)

如果我转换为double,那么,当然,我失去了精度:

double dx = x;
double dy = y;
double …
Run Code Online (Sandbox Code Playgroud)

.net c# long-integer

102
推荐指数
7
解决办法
8122
查看次数

通过快速浮点倒数有效计算2**64 /除数

我目前正在研究如何使用各种现代处理器的快速单精度浮点倒数功能来计算基于定点Newton-Raphson迭代的64位无符号整数除法的起始近似.它需要尽可能精确地计算2 64 /除数,其中初始近似必须小于或等于数学结果,基于以下定点迭代的要求.这意味着这种计算需要低估.我目前有以下代码,基于广泛的测试,效果很好:

#include <stdint.h> // import uint64_t
#include <math.h> // import nextafterf()

uint64_t divisor, recip;
float r, s, t;

t = uint64_to_float_ru (divisor); // ensure t >= divisor
r = 1.0f / t;
s = 0x1.0p64f * nextafterf (r, 0.0f);
recip = (uint64_t)s; // underestimate of 2**64 / divisor 
Run Code Online (Sandbox Code Playgroud)

虽然这段代码很实用,但在大多数平台上并不是很快.一个显而易见的改进,需要一些特定于机器的代码,是r = 1.0f / t用代码来替换除法,该代码利用硬件提供的快速浮点倒数.这可以通过迭代来增强,以产生在数学结果的1 ulp内的结果,因此在现有代码的上下文中产生低估.x86_64的示例实现将是:

#include <xmmintrin.h>
/* Compute 1.0f/a almost correctly rounded. Halley iteration with cubic convergence */
inline float fast_recip_f32 (float a)
{
    __m128 t; …
Run Code Online (Sandbox Code Playgroud)

c floating-point bit-manipulation division

17
推荐指数
1
解决办法
486
查看次数

计算 2^2?% uint64_t

如何有效计算 2\xc2\xb9\xc2\xb2\xe2\x81\xb8 % n,其中 n 为uint64_t(且非零)?

\n

如果我能够像_udiv128MSVC 的内在那样缩小范围,我可以这样做:

\n
uint64_t remainder;\n_udiv128(1, 0, n, &remainder);\n_udiv128(remainder, 0, n, &remainder);\n
Run Code Online (Sandbox Code Playgroud)\n

但这是两条慢指令,更不用说像 ARM 这样的 CPU 没有缩小除法。有没有更好的办法?

\n

相关:如何在 C 中计算 2\xe2\x81\xb6\xe2\x81\xb4/n?

\n

c optimization assembly integer-division

7
推荐指数
1
解决办法
284
查看次数

欺骗将常数(2的幂)除以整数

注意这是一个理论问题.我很满意我的实际代码的性能.我只是想知道是否有其他选择.

是否有一个技巧可以通过整数变量值对一个常量值进行整数除法,该整数除法本身就是2的整数次幂,而不必使用实际的除法运算?

// The fixed value of the numerator
#define SIGNAL_PULSE_COUNT 0x4000UL

// The division that could use a neat trick.
uint32_t signalToReferenceRatio(uint32_t referenceCount)
{
    // Promote the numerator to a 64 bit value, shift it left by 32 so
    // the result has an adequate number of bits of precision, and divide
    // by the numerator.
    return (uint32_t)((((uint64_t)SIGNAL_PULSE_COUNT) << 32) / referenceCount);
}
Run Code Online (Sandbox Code Playgroud)

我找到了几个(很多)参考,用于通过常量,整数和浮点进行除法的技巧.例如,问题什么是将整数除以3的最快方法?有很多好的答案,包括参考其他学术和社区材料.

鉴于分子是常数,并且它是2的整数幂,是否有一个巧妙的技巧可以用来代替实际的64位除法; 某种逐位操作(移位,AND,XOR,那种东西)或类似的操作?

由于仪器的精度取决于此测量的精度,因此我不希望任何精度损失(超出可能由于整数舍入导致的半位)大于实际除法的精度.

"让编译器决定"不是答案,因为我想知道是否有诀窍.

额外的,上下文信息

我正在开发一个16位数据,24位指令字微控制器的驱动程序.驱动器对外围模块做了一些魔术,以获得信号频率的固定数量脉冲的参考频率的脉冲计数.所需结果是信号脉冲与参考脉冲的比率,表示为无符号32位值.该函数的算法由我正在为其开发驱动程序的设备的制造商定义,并且结果被进一步处理以获得浮点实际值,但这超出了该问题的范围.

我正在使用的微控制器有一个数字信号处理器,它有许多我可以使用的除法操作,如果有必要,我不害怕这样做.会有这种方法克服,超越放在一起汇编指令,使其工作,如DSP被用来做一个BLDC驱动ISR一个PID功能一些小的挑战,但没有什么我不能管理.

c theory optimization integer-arithmetic

6
推荐指数
1
解决办法
820
查看次数