如何使用 frexp 实现双变量的模运算符?

2023-12-12

我正在关注Kernighan&Pike“UNIX 编程环境”.

书中的一个练习(练习 8-2,第 241 页)要求实现模运算符 (%)double变量在C.

So:

4.6 % 2.1 = 0.4
4.0 % 3.0 = 1.0

因此基本上是在实施dmod using frexp:

dmod(4.6, 2.1) would return 0.4
dmod(4,0, 3.0) would return 1.0

我看过这个帖子:在定点类型上实现模数它定义了一个算法来实现这个运算符。

但这本书建议作为阅读的提示frexp(3),所以我想可以使用该函数来做到这一点。

现在,如果我正确理解了手册页,该函数会执行类似(伪代码)的操作:

a,b -- double variables
a_exp,b_exp -- integer exponents for frexp
a_x = frexp(a,&a_exp) --> a = a_x * 2^a_exp
b_x = frexp(b,&b_exp) --> b = b_x * 2^b_exp
c=a/b
c_exp -- integer exponent for frexp
c_x = frexp(c,&c_exp) --> c = c_x * 2^c_exp

但我仍然不知道如何混合这些值来获得模运算符。

这本书很旧,可能有更好的方法来做到这一点,但问题更具学术性,并且对于理解如何实现这一点仍然有效frexp.


我不知道作者对浮点数模假设的规范是什么。我在这里假设它们指的是标准 C 库函数的功能fmod().

最简单的实现方式fmod()是使用二进制普通除法,它在循环中产生除法的商,每次迭代产生一位商位。重复此操作,直到商的所有整数位都用完,同时保留部分余数。在该过程结束时,最终的余数代表期望的结果。

要开始普通除法,我们必须在开始时将除数与被除数正确对齐。这是通过缩放使得被除数 >= 除数 > 被除数/2 来实现的。指某东西的用途frexp()和这个结合ldexp()提供基于指数的粗略缩放,可能需要根据有效数(尾数)进行细化。

示例性 ISO-C99 实施fmod()如下所示。实施remainder()看起来类似,但有点复杂,因为需要将商舍入到最接近的或偶数,而不是截断它。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>

/* returns the floating-point remainder of a/b (rounded towards zero) */
double my_fmod (double a, double b)
{
    const double NAN_INDEFINITE = 0.0 / 0.0;
    double r;
    if (isnan (a) || isnan (b)) {
        r = a + b;
    } else if (isinf (a) || (b == 0.0)) {
        r = NAN_INDEFINITE;
    } else {
        double fa, fb, dividend, divisor;
        int expo_a, expo_b;
        fa = fabs (a);
        fb = fabs (b);
        if (fa >= fb) {
            dividend = fa;
            /* normalize divisor */
            (void)frexp (fa, &expo_a);
            (void)frexp (fb, &expo_b);
            divisor = ldexp (fb, expo_a - expo_b);
            if (divisor <= 0.5 * dividend) {
                divisor += divisor;
            }
            /* compute quotient one bit at a time */
            while (divisor >= fb) {
                if (dividend >= divisor) {
                    dividend -= divisor;
                }
                divisor *= 0.5;
            }
            /* dividend now represents remainder */
            r = copysign (dividend, a);
        } else {
            r = a;
        }
    }
    return r;
}

/*
  From: geo <[email protected]>
  Newsgroups: sci.math,comp.lang.c,comp.lang.fortran
  Subject: 64-bit KISS RNGs
  Date: Sat, 28 Feb 2009 04:30:48 -0800 (PST)

  This 64-bit KISS RNG has three components, each nearly
  good enough to serve alone.    The components are:
  Multiply-With-Carry (MWC), period (2^121+2^63-1)
  Xorshift (XSH), period 2^64-1
  Congruential (CNG), period 2^64
*/

static uint64_t kiss64_x = 1234567890987654321ULL;
static uint64_t kiss64_c = 123456123456123456ULL;
static uint64_t kiss64_y = 362436362436362436ULL;
static uint64_t kiss64_z = 1066149217761810ULL;
static uint64_t kiss64_t;

#define MWC64  (kiss64_t = (kiss64_x << 58) + kiss64_c, \
                kiss64_c = (kiss64_x >> 6), kiss64_x += kiss64_t, \
                kiss64_c += (kiss64_x < kiss64_t), kiss64_x)
#define XSH64  (kiss64_y ^= (kiss64_y << 13), kiss64_y ^= (kiss64_y >> 17), \
                kiss64_y ^= (kiss64_y << 43))
#define CNG64  (kiss64_z = 6906969069ULL * kiss64_z + 1234567ULL)
#define KISS64 (MWC64 + XSH64 + CNG64)

double int64_as_double (int64_t a)
{
    double r;
    memcpy (&r, &a, sizeof r);
    return r;
}

int32_t double_as_int64 (double a)
{
    int64_t r;
    memcpy (&r, &a, sizeof r);
    return r;
}

int main (void)
{
    double a, b, res, ref;
    uint64_t i = 0;
    do {
        a = int64_as_double (KISS64);
        b = int64_as_double (KISS64);
        ref = fmod (a, b);
        res = my_fmod (a, b);
        if (double_as_int64 (res) != double_as_int64 (ref)) {
            printf ("error: a=% 23.16e b=% 23.16e res=% 23.16e ref=% 23.16e\n", a, b, res, ref);
            return EXIT_FAILURE;
        }
        i++;
        if (!(i & 0xfffff)) printf ("\r%llu", i);
    } while (i);
    return EXIT_SUCCESS;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 frexp 实现双变量的模运算符? 的相关文章

  • 不同提供商的相同 EDMX 文件

    我正在开发一个项目 其中有一个本地数据库 SQL CE 在不存在与服务器的连接的情况下用作缓冲区 在服务器上我想使用相同的数据库布局 当然 我想使用服务器和客户端上可用的 Common dll 中的相同 EDMX 文件 在客户端中 我有一个
  • 使用sqlbulkcopy之前如何创建表

    我有一个 DBF 文件 我正在尝试导入该文件 然后将其写入 SQL 表 我遇到的问题是 如果我使用 SqlBulkCopy 它需要我提前创建表 但在我的场景中这是不可能的 因为 dbf 文件不断变化 到目前为止 这是我的代码 public
  • 成员字段、构建顺序

    在 C 中 当执行如下所示的操作时 构造顺序是否得到保证 Logger Logger kFilePath logs runtime log logFile kFilePath 是的 施工顺序始终得到保证 但是 不能保证它与对象在初始值设定项
  • 套接字编程-listen() 和accept() 有什么区别?

    我一直在读本教程 http www cs rpi edu moorthy Courses os98 Pgms socket html了解套接字编程 看来listen and accept 系统调用都做同样的事情 即阻塞并等待客户端连接到使用
  • 显示 div 内的用户名列表

    我是 jQuery 新手 在我的项目中 我创建了一个类User其中代码如下所示 static ConcurrentDictionary
  • 在异步请求中使用超时回调

    我之前问过这个问题 但我将用提出的解决方案来完成这个问题 并提出另一个问题 我正在使用这个类来进行异步网络请求 http msdn microsoft com en us library system net webrequest aspx
  • ASMX Web 服务,测试表单仅在本地计算机上适用于一种 WebMethod

    我有一个正在测试的 ASMX WebService 并且在大多数方法上我都可以使用测试表单进行测试 然而 我确实有一种方法 测试表上写着 The test form is only available for requests from t
  • 如何将 Visual-Studio 2010 切换到 c++11

    我是 c 编程新手 我想尝试 c 11 新功能 那么我要问的是如何切换 Visual studio 2010 才能编译 c 11 源代码 你可以参考这个表 VC10 中的 C 0x 核心语言功能 表格 http blogs msdn com
  • C# 实体框架我们应该使用 POCO.Id 还是仅使用 POCO 设置关系?

    我在服务方法中遇到一种情况 将 POCO 分配为另一个 POCO 的子对象无法按预期工作 我正在使用实体框架 4 public void ChangeOrderCurrency Currency currency order Currenc
  • 为什么我在 WinForms 列表框中得到“System.Data.DataRowView”而不是实际值?

    每当我运行代码并尝试查看highscore我在列表框中得到的只是System Data DataRowView 谁能明白为什么吗 Code MySqlConnection myConn new MySqlConnection connStr
  • 使用 catch all 字典属性将 json 序列化为对象

    我想使用 JSON net 反序列化为对象 但将未映射的属性放入字典属性中 是否可以 例如给定 json one 1 two 2 three 3 和 C 类 public class Mapped public int One get se
  • 何时分离或加入 boost 线程?

    我有一个方法 大约每 30 秒触发一次 我需要在一个线程中包含它 我有一个可以从类外调用的方法 像 call Threaded Method 这样的东西会创建一个线程 该线程本身会调用最终的线程方法 这些是 MyClass 的方法 void
  • 禁用实体框架的默认值生成(Code First)

    我数据库中有一个列不能为空 我想将其设置为默认值在数据库中 问题是实体框架似乎自己创建了一个默认值 例如 int gt 0 并且完全忽略了数据库中的默认值约束 有没有办法禁用实体框架的默认值 我发现您可以使用以下属性来装饰您的字段 Data
  • List 或其他类型上的 string.Join

    我想将整数数组或列表转换为逗号分隔的字符串 如下所示 string myFunction List
  • 如何在 ASP.NET Core 项目中使用 MStest 测试 Ok() 结果

    我正在使用 MStest 来测试我的控制器 我想测试这个动作 HttpGet Name GetGroups public async Task
  • 如何阻止 Control-I 在 CoreWindow 范围内的 UWP 文本框中插入选项卡?

    当我在 UWP 应用程序中有一个 TextBox 时 对我来说 奇怪的行为 在 Windows 10 中创建通用的空白应用程序 UWP 应用程序 使用以下代码将文本框添加到默认网格
  • 按 Enter 继续

    这不起作用 string temp cout lt lt Press Enter to Continue cin gt gt temp cout lt lt Press Enter to Continue cin ignore 或更好 in
  • C# 模式匹配

    我对 C 有点陌生 我正在寻找一个字符串匹配模式来执行以下操作 我有一个像这样的字符串 该书将在 唐宁街 11 号接待处 并将由主要医疗保健人员参加 我需要创建一个 span 标签来使用 startIndex 和 length 突出显示一些
  • 如何获取运行或段落的高度

    我找到了Run or Paragraph in FlowDocument现在我需要知道HEIGHT of it i e while navigator CompareTo flowDocViewer Document ContentEnd
  • 查找和替换正则表达式问题

    感谢这里对我其他问题的所有大力帮助 我开始掌握正则表达式 但我仍然对这个一无所知 我的代码是 StreamReader reader new StreamReader fDialog FileName ToString string con

随机推荐

  • Rust 中具有变化行为的有限(游戏)状态机模式?

    我正在尝试用 Rust 编写一个回合制游戏 但我在该语言中遇到了障碍 除非我没有完全理解某些东西 我是该语言的新手 基本上 我想更改游戏中的状态 其中每个状态都有不同的行为 例如我有类似的东西 struct Game state Some
  • pyspark rdd isCheckPointed() 为 false

    当我向 pyspark 数据帧迭代添加 500 多列时 遇到了 stackoverflowerrors 所以 我包括了检查点 检查站没有帮助 因此 我创建了以下玩具应用程序来测试我的检查点是否正常工作 我在此示例中所做的就是通过一遍又一遍地
  • 如何以编程方式关闭应用程序?

    我正在寻找完全关闭我的应用程序的按钮的代码 我尝试使用谷歌的一些东西 但我的应用程序仍在后台运行 我需要完全关闭它 有代码可以做到这一点吗 为什么你需要真正关闭你的应用程序 假设它只是一个普通的应用程序 没有运行任何后台服务或持有唤醒锁 你
  • 在 Mac OS X 10.6 上卸载 Ruby on Rails

    我正在尝试让 RoR 启动并运行 mysql 数据库 但这对我来说似乎是不可能的 在包含 mysql gem 时出现错误 所以我尝试通过控制台做很多事情但没有结果 我不记得我做了什么 所以 我想删除所有内容并从cero重新开始 如何从 Ma
  • 如何使用kivy处理android运行时权限

    我发现 kivy 是构建跨平台应用程序的非常好的框架 并且我对 kivy 非常感兴趣 只是为了做 android 应用程序 因为我认为在 kivy 中很容易和舒适 在尝试了几个例子之后 我有兴趣知道应该如何处理 kivy 应用程序的 and
  • 从 Oracle 数据库转换字符串与 AM/PM 日期时间

    我的时间戳格式为03 AUG 12 08 15 00 000000000 PM 05 00我无法获得String形式上的表示yyyy MM dd HH mm ss 这是我的代码 public static void convert Stri
  • requirejs blueimp fileuploader 仅加载 min.js 文件,不加载其他文件

    所以我是 requirejs 和backbone 的菜鸟 但我试图在本地计算机上加载blueimp 文件上传器的所有依赖项 而不加载任何外部脚本 这是我的 config js 文件 Set the require js configurat
  • 如何从linux程序将输入逐行输入到python?

    我想通过管道输出ps ef逐行转换为 python 我正在使用的脚本是这个 first py usr bin python import sys for line in sys argv print line 不幸的是 行 被分成由空格分隔
  • 没有动作的意图过滤器

    Android 的文档说 http developer android com reference android content IntentFilter html 如果任何给定值与意图操作匹配 或者过滤器中未指定任何操作 则操作匹配 我
  • QML:GridView 在 C++ 中更改模型后不更新

    我的起点是以下 QML 源 其 中 GridView 显示 ListModel 以及项目交换的漂亮动画 import QtQuick 1 1 GridView id mainGrid width 825 height 400 cellWid
  • 使用 xpath 从背景图像样式属性中提取值

    ii 具有以下结构 div class xGh style background image none div 我需要那个输出 name file jpg 我尝试用它answer 但不适合我 img xpath gt query subst
  • 比较 shell 脚本中的两个版本号

    我有一个文件file1如下所示 包含当前版本号和预期版本号 CurrV 1 5 2 ExpecV 1 8 1 我想编写一个 bash 脚本来比较这两个值 如果ExpecV gt CurrV那我应该echo SUCCESS 否则我应该echo
  • Numpy 数组索引和/或添加似乎很慢

    我正在对 numpy 数组进行基准测试 因为当我尝试在脚本中用 numpy 数组替换 python 数组时 结果比预期的要慢 我知道我错过了一些东西 我希望有人能澄清我的无知 我创建了两个函数并为它们计时 NUM ITERATIONS 10
  • 仅在 tumblr 博客主页上显示 div?

    我对 CSS 和 HTML 的理解相当新手 我正在尝试做一些我认为应该相对简单的事情 在我正在创建的自定义 tumblr 主题中 但我找不到简单的答案 我有一种感觉 可能有一种超级简单的方法可以在 JavaScript 中完成我想要的事情
  • 将 .cpp 文件编译为程序内部的 EXE(EXE 文件)[关闭]

    很难说出这里问的是什么 这个问题模棱两可 含糊不清 不完整 过于宽泛或言辞激烈 无法以目前的形式合理回答 如需帮助澄清此问题以便重新打开 访问帮助中心 我想做一个程序 EXE文件 它将采用用户定义的设置并在前面提到的程序 EXE 内为用户创
  • 具有任意数量集合的 Python itertools.product

    我希望执行以下代码 temp temp append 1 2 temp append 3 4 temp append 5 6 print list itertools product temp 0 temp 1 temp 2 但是 我想以任
  • Python 替换 PHP 的标头

    如何在 python 中发送原始 http 标头 就像 PHP 中的 header 一样 在 Django 中 你会像 def someview request etc out HttpResponse outputstring mimet
  • 在 C++ 服务和用户模式应用程序崩溃后收集崩溃 .dmp 和 .hdmp 文件

    我正在使用 WinAPI 在 C MFC 中进行编码 我的软件由本地服务和用户模式应用程序组成 该应用程序为登录的 Windows 用户提供用户界面 我正在寻找一种方法来收集 dmp 和 hdmp 文件 以防这些模块中的任何一个发生崩溃 我
  • Android:下载文件并保存在 SD 卡上

    正在尝试创建一个应用程序来下载 SD 卡上的文件 这是我的代码 public class MainActivity extends Activity Override protected void onCreate Bundle saved
  • 如何使用 frexp 实现双变量的模运算符?

    我正在关注Kernighan Pike UNIX 编程环境 书中的一个练习 练习 8 2 第 241 页 要求实现模运算符 double变量在C So 4 6 2 1 0 4 4 0 3 0 1 0 因此基本上是在实施dmod using