在 32 位机器中存储临时 64 位变量

Posted

技术标签:

【中文标题】在 32 位机器中存储临时 64 位变量【英文标题】:Store temporary 64 bit variable in a 32 bit machine 【发布时间】:2019-10-29 17:04:10 【问题描述】:

我正在 32 位机器上进行一些编程。 作为计算 3d 对象之间碰撞的算法的一部分,我必须得到点积的结果:

    //Vector3 components are signed int
    signed long GaMhVecDotL(const Vector3 *p_a, const Vector3 *p_b)
    
        return ((p_a->vx * p_b->vx + p_a->vy * p_b->vy + p_a->vz * p_b->vz));
    

在某些情况下,此结果会溢出 32 位返回值 (signed long)。 我尝试了几件事:

    在将 Vector3 组件发送到此函数之前对其进行位移 以减小尺寸。这在大多数情况下都有效,但我失去了精度和 这使得算法在某些边缘情况下失败。 将运算结果存储在long long 变量中, 虽然它编译它似乎并没有存储变量 正确(这是针对某些 PSX 自制软件,编译器和工具自 90 年代后期以来未更新)。

我实际上不需要知道点积的完整结果,我只需要知道结果是正数、负数还是 0,同时尽量保持精度.

有什么方法可以将该操作的结果 (p_a->vx * p_b->vx + p_a->vy * p_b->vy + p_a->vz * p_b->vz) 存储在一个临时 64 位 var(或 2x32 位)中,以便我稍后检查该 var 是正数、负数还是 0?

【问题讨论】:

"我已经尝试了几件事" - 然后请显示您尝试过的实际代码,而不仅仅是对您认为您尝试过的内容的模糊描述。我们无法调试释义。 【参考方案1】:

有什么方法可以将该操作的结果 (p_a->vx * p_b->vx + p_a->vy * p_b->vy + p_a->vz * p_b->vz) 存储在临时 64 位 var(或 2x32 位)中,以便我稍后检查该 var 是正数、负数还是 0?

这使用 32 位数学,(给定 int 是 32 位)。将返回值存储在 64 位结果中不会使等式变为 64 位。

// 32-bit math
p_a->vx * p_b->vx + p_a->vy * p_b->vy + p_a->vz * p_b->vz

相反,在等式中使用 64 位数学。

//               v-----------------v multiplication now done as 64-bit
long long dot = (1LL*p_a->vx*p_b->vx) + (1LL*p_a->vy*p_b->vy) + (1LL*p_a->vz*p_b->vz);

然后检查签名

if (dot < 0) return -1;
return dot > 0;

【讨论】:

非常感谢 chux 提供答案!不幸的是,使用“long long”变量似乎不适用于平台(Play Station 1)。让我们编译,但结果到处都是。据我所知,PSX 编译器是 90 年代 gcc 的自定义版本,似乎引擎盖下不能很好地处理这个临时 64 变量:( @Walrfi 你是如何确定“结果无处不在”的? 例如 A(1248, 0, 46080) * B(-2541, -137, 1011) 的结果给我 -1 但它应该是 +1 (43415712) @Walrfi 您的 int 是 32 位还是 16 位?需要的是一个代码示例。 "编译器和工具自 90 年代后期以来一直没有更新",因此与 1LL 的乘法有可能在忽略隐式转换或隐式转换被忽略或被忽略的情况下得到优化以错误的方式实施。我会尝试在任何地方使用显式强制转换 ((long long)(p_a-&gt;vx)*(long long)(p_b-&gt;vx)+...)。

以上是关于在 32 位机器中存储临时 64 位变量的主要内容,如果未能解决你的问题,请参考以下文章

第二章 变量和基本类型

java 在我的 64 位机器的任务管理器中显示为 32 位

计算机系统漫游笔记

计算机操作系统

64位机器上的结构填充

在 Intel CPU 上选择 32 位和 64 位固有 CRC