在进行我自己的BigInteger实现时,我遇到了扩展的GCD算法,这是寻找模乘法逆的基础.由于众所周知的欧几里德方法执行速度太慢,混合和二进制算法的速度只有5-10倍,因此选择Lehmer对经典算法的修改.但困难在于,当谈到描述Lehmer时,我发现的所有书籍(Knuth,应用密码学手册,互联网等)都有同样的缺点:
至于第一个问题,我最初感到惊讶的是无法找到任何实际的实现(不要指向我的GNU MP库 - 它不是学习的源),但最终通过反编译微软的实现获得灵感来自.Net 4.0,显然是基于Jebelean撰写的文章" 用于查找长整数GCD的两位数Lehmer-Euclid算法 "的思想.由此产生的功能很大,看起来很可怕,但效果很好.
但Microsoft的库仅提供基本功能,不计算任何辅助因子.嗯,准确的,一些辅助因子都在速记步计算,并且在第一步的辅助因子简单地是初始的,但在执行手写步骤之后,那么他们就不再匹配.我目前的解决方案是将"真实"辅助因子与"替代"辅助因子并行更新(第一步除外),但它使性能降至零以下:此功能现在仅比二进制文件快25-50%基本模式下的方法.因此,问题在于,虽然输入数字仅在长手步骤中完全更新,但辅助因子也会在每个速记步骤的迭代中更新从而摧毁了莱默方法的几乎任何好处.
为了加快速度,我实现了一个"融合乘法 - 加法"函数,因为"融合乘法 - 乘法 - 减法"确实有助于更新输入数字,但这次影响可以忽略不计.另一个改进是基于这样的事实,即通常只需要一个辅助因子,因此另一个辅助因子根本就不能计算.这应该减少开销(或者更多,因为第二个数字通常明显小于第一个数字),但实际上开销仅减少了预期的 25%到50%.
因此,我的问题归结为:
因此,尽管我对基本算法的性能感到满意,但是相反的情况适用于扩展操作模式,这在我的情况下是主要的.
algorithm computability discrete-mathematics greatest-common-divisor
某些CPU架构(x86除外)不喜欢在未对齐的地址读取和写入多字节数字,以至于在检测到这种情况时会引发SIGBUS异常,并迫使程序员按字节顺序手动完成所有操作.虽然对于需要这个的平台可能无法做任何事情,但检查对齐并在允许未对齐访问的平台(例如x86)上执行逐字节操作将是愚蠢的.问题是:C/C++编译器是否定义了一个表示对齐要求的常量?
目前,我正在使用这个:
#if defined(_M_IX86) | defined(__i386) | defined(__i386__) | defined(i386) | defined(_X86_)
// Unaligned access is allowed.
#elif defined(_M_X64) | defined(__x86_64__) | defined(__x86_64) | defined(__amd64) | defined(__amd64__) | defined(_M_AMD64)
// Unaligned access is allowed.
#else
#define ALIGNED_ACCESS_ONLY
#endif
Run Code Online (Sandbox Code Playgroud)
但它看起来太"家酿":它不是指示当前硬件平台的实际属性,而是描述了我自己对x86-32和x86-64的考虑以及这些平台最常用的常量名称.
大多数 POSIX 兼容系统提供获取或设置高分辨率计时器之一的函数:
\n\nint clock_gettime(clockid_t clock_id, struct timespec *tp);\nRun Code Online (Sandbox Code Playgroud)\n\n每个系统的文档通常列出几个符号名称作为可能的clock_id值,但从未提及实际的数值。事实证明,不仅不同系统的数值不同,而且相同含义的符号名称也不同。更重要的是,并非系统实际支持的所有时钟都在time.h ( bits/time.h ) \xc2\xad\xe2\x80\x94 中定义,有些仅在linux/time.h中定义。
也就是说,在Linux系统中我们可能有:
\n\n#define CLOCK_REALTIME 0\n#define CLOCK_MONOTONIC 1\n#define CLOCK_PROCESS_CPUTIME_ID 2\n#define CLOCK_THREAD_CPUTIME_ID 3\n#define CLOCK_MONOTONIC_RAW 4\n#define CLOCK_REALTIME_COARSE 5\n#define CLOCK_MONOTONIC_COARSE 6\n#define CLOCK_BOOTTIME 7\n#define CLOCK_REALTIME_ALARM 8\n#define CLOCK_BOOTTIME_ALARM 9\n#define CLOCK_SGI_CYCLE 10 // In linux/time.h only.\n#define CLOCK_TAI 11 // In linux/time.h only.\nRun Code Online (Sandbox Code Playgroud)\n\n在 Cygwin 环境中(不是逐字摘录):
\n\n#define CLOCK_REALTIME 1 // Means CLOCK_MONOTONIC?\n#define CLOCK_MONOTONIC 4 // Means CLOCK_MONOTONIC_RAW?\n#define CLOCK_PROCESS_CPUTIME_ID 2\n#define CLOCK_THREAD_CPUTIME_ID 3\nRun Code Online (Sandbox Code Playgroud)\n\n … 由于Bash在set -o nounset模式(aka set -u)中运行时 可能会认为空数组未设置,无论它们是否实际上已分配了空值,因此在尝试扩展数组时必须小心 - 其中一个解决方法是检查数组长度是否为零.更不用说获取数组中的元素数量本身就是一种常见的操作.
在openSUSE 42.1中使用Bash 4.2.47(1) - release发展时,我习惯于${#ARRAY_NAME[@]}在数组为空或未设置时获得成功的数组大小 .但是,在FreeBSD 10.3中使用Bash 4.3.46(1)-release检查我的脚本时,结果发现此操作可能会失败并显示通用的"未绑定变量"错误消息.提供扩展的默认值似乎不适用于数组长度.提供替代命令链似乎有效,但不能在通过子shell扩展调用的函数内部 - 函数只在第一次失败后退出.还有什么可以帮到这里?
请考虑以下示例:
function Size ()
{
declare VAR="$1"
declare REF="\${#${VAR}[@]}"
eval "echo \"${REF}\" || echo 0" 2>/dev/null || echo 0
}
set -u
declare -a MYARRAY
echo "size: ${#MYARRAY[@]}"
echo "size: ${#MYARRAY[@]-0}"
echo "Size: $(Size 'MYARRAY')"
echo -n "Size: "; Size 'MYARRAY'
Run Code Online (Sandbox Code Playgroud)
在openSUSE环境中,所有echo行都0按预期输出 .在FreeBSD中,同样的结果是唯一可能当该阵列被显式分配一个空值:MYARRAY=(); 否则,前两行中的内联查询都会失败,第三行只是输出Size:(意味着扩展结果为空),只有最后一行完全由于外部成功|| echo 0 - …
我正在制作一个在控制台模式下工作的交互式基准测试程序,并希望能够通过按Ctrl + C或Ctrl + Break一次中断当前计算,而后续按下应该像往常一样,终止程序.但是,如果当前没有执行任何计算,则第一次按Ctrl + C将导致终止.
起初,这看起来像一个简单的任务.我创建了一个带有明显EnableHandler()和DisableHandler()例程的静态类,以及一个依赖于先前状态的行为的处理函数:如果已经请求中断,那么只需停下来返回,否则设置arg.Cancel并引发中断请求标志.因此,当基准测试开始时,它启用处理程序,然后检查每个主要周期的中断标志; 完成后,如果需要,它会禁用处理程序并将中断请求传播到最顶层的调用者.
但是,这种方法只能运行一次:第一次删除处理程序后(无论是否曾经被触发),之后再次安装它不再有效 - 操作不会产生错误,但处理程序永远不会收到事件发生时控制.这是.NET事件处理中的预期行为吗?
关于Console.CancelKeyPressSO和其他论坛有很多主题,但几乎没有人考虑删除处理程序,因此难怪他们没有遇到麻烦.尽管如此,在" 如何多次使用ConsoleCancelEventHandler "中提到了一些类似的(?)问题,但该应用程序是一个复杂的GUI前端,用于按需启动的几个外部控制台实用程序,该问题显然与尝试时出现的显式异常有关.第二次添加处理程序, - 这不是我的情况.
在被告知安慰各种.NET版本操作相关先前存在的bug,如果这样的行为是不正常的,通过.NET故障引起的或特定于Visual Basic,我不会感到惊讶,(我不知道是否AddHandler和RemoveHandler在VB.NET完全等同于C#中的+=和-=事件运算符.我目前在Windows 7 x86-64上使用.NET 4.5和Visual Basic 2012,并安装了所有可用的更新.
作为一种解决方法,我实际上不会在DisableHandler()例程中删除处理程序,而只是切换一个标志:当清除此标志时,处理程序立即返回,就好像没有安装一样.但是,这种方法对我来说看起来很难看,我希望以适当的方式解决问题并实现目标.
PS.Chris Dunaway要求的当前代码:
' Usage example
Dim fAbort As Boolean = False
BreakHandler.Enable()
For Each oImplementation As Implementation In oCompetition.Implementations
Benchmark(oImplementation)
If BreakHandler.AbortRequested() Then fAbort = True : Exit For
Next
BreakHandler.Disable()
Return …Run Code Online (Sandbox Code Playgroud) 尝试使用Bash内置的正则表达式匹配来解析以下类型的字符串,这些字符串将被转换为Perl替换表达式(引号不是数据的一部分)
'~#A#B#'
#^ ^ ^-- Replacement string.
#| +---- Pattern string.
#+------ Regular expression indicator (no need to escape strings A and B),
# which is only allowed if strings A and B are surrounded with ##.
# Strings A and B may not contain #, but are allowed to have ~.
'#A#B#'
#^------ When regex indicator is missing, strings A and B will be escaped.
'A#B'
# Simplified form of '#A#B#', i. e. without the enclosing ##.
# Still …Run Code Online (Sandbox Code Playgroud)