【问题标题】:How to set the sign of a value based on another如何根据另一个值设置一个值的符号
【发布时间】:2015-05-15 12:27:01
【问题描述】:

我正在使用一个 php 脚本,该脚本有一个可以给我一个数字的计算。计算本身是一个黑匣子,我使用一个返回数字的函数来访问它。

所以:

$num = doCalc($some_arguments); //$num now has a non-zero numeric value

现在,我想要基于另一个数字的符号的$num to be positive or negative 的符号。我知道我可以使用“if-else”来做到这一点,但我正在尝试检查没有逻辑分支的最佳方法。

这就是我将 $anotherNum 的符号应用于 $num 的方法:

$anotherNum = -10; //for example...
$num = doCalc($some_arguments); //lets assume $num is 100...
$num = abs($num) * ($anotherNum/abs($anotherNum))

我不确定这是否是正确的方法,或者 PHP 是否具有可以使这变得容易的函数。任何指针,任何人?

谢谢。

【问题讨论】:

  • 我喜欢@Spektre 给出的答案,但如果你真的想避免任何类型的比较逻辑,那么我喜欢你的方法。也许您可以通过将除法转换为 ingeger 来缓解精度问题? $num = abs($num) * (int)($anotherNum/abs($anotherNum))

标签: php algorithm logic negative-number


【解决方案1】:

您可以通过多种方式做到这一点,由于乘法和除法,您的方法可以更改总和值精度(在浮点数上)...这里有更多选项让 a 成为您的 numb anothernum

  1. 如果将不同极性的数相乘,则结果为负

    if ((a*b)<0.0) a=-a;
    
  2. 避免计算

    if (((a<0.0)&&(b>0.0))||((a>0.0)&&(b<0.0))) a=-a;
    
  3. 符号位提取

    • 在大多数语言/平台中,符号通常是展位整数和浮动值的数字的 MSB,所以在这种情况下
    • 对于 32 位浮点值:

      unsigned int sa=(unsigned int*)(&a)[0]>>31;
      unsigned int sb=(unsigned int*)(&b)[0]>>31;
      if (sa!=sb) a=-a;
      
    • 对于 32 位整数值:

      if ((a&0x80000000)!=(b&0x80000000)) a=-a;
      
    • 不管你是移位还是位掩码...
    • 对于 64 位值,使用 64 位变量并将位移位更改为 63
    • 或将另外 8 个零添加到掩码十六进制数

[注释]

  • 现在您只需添加b==0 时的情况 ...

[edit1] 浮点数没有 if/else

float a,b; // these are you numbers
unsigned int *pa=(unsigned int*)(&a);
unsigned int *pb=(unsigned int*)(&b);
*pa=((*pa)&0x7FFFFFFF)|((*pb)&0x80000000);
  • 那么只需将符号位从a 复制到b
  • pa,pb 只是将 a,b 处理为整数类型以进行位访问的指针
  • 前半部分清除 a 中的符号位
  • second 从 b 复制符号位

【讨论】:

  • 感谢您的回答......但是我试图在没有 if/else 条件的情况下这样做......
  • @UndefinedVariable 对浮点数使用位操作很容易看到整数的 [edit1] 只有当你的数字有单独的符号位而不是 2os 补码时才有可能
猜你喜欢
  • 1970-01-01
  • 2022-01-08
  • 2019-12-16
  • 2019-11-02
  • 2018-12-26
  • 1970-01-01
  • 2022-01-10
  • 2021-04-10
  • 2016-04-23
相关资源
最近更新 更多