1

我有一个使用 long 的 8 字节定点数,其恒定分母为 (1 << 24)。如何对两个 Fixed8 值进行除法?由于我使用的是 C#,因此我不能简单地转换为更大的整数。还是我在语言上想太多了?

谢谢。

public struct Fixed8
{
    private long _numerator;
    public const long DENOMINATOR = 1 << 24;
}
4

4 回答 4

1

这是一种将所有计算保存在longs 中的方法。不过,它可能不会更快。我没有量过。

public struct Fixed8
{
    public Fixed8(double value)
    {
        _numerator = (long)(value * DENOMINATOR);
    }

    private long _numerator;
    public const long DENOMINATOR = 1 << 24;

    public static Fixed8 operator /(Fixed8 a, Fixed8 b)
    {
        long remainder;
        long quotient = Math.DivRem(a._numerator, b._numerator, out remainder) * DENOMINATOR;

        long morePrecision = remainder * DENOMINATOR / b._numerator;

        return new Fixed8 { _numerator = quotient + morePrecision };
    }
}
于 2012-10-13T22:57:42.053 回答
1

您可以使用BigInteger 结构来执行计算:

public static Fixed8 operator /(Fixed8 a, Fixed8 b)
{
    Fixed8 result;
    result._numerator = (long)( new BigInteger(a._numerator) *
                                new BigInteger(DENOMINATOR)  /
                                new BigInteger(b._numerator) );
    return result;
}

完整代码:

public const long DENOMINATOR = 1 << 24;

private long _numerator;

public Fixed8(double value)
{
    _numerator = (long)(value * DENOMINATOR);
}

public static Fixed8 operator /(Fixed8 a, Fixed8 b)
{
    Fixed8 result;
    result._numerator = (long)( new BigInteger(a._numerator) * 
                                new BigInteger(DENOMINATOR)  / 
                                new BigInteger(b._numerator) );
    return result;
}

public static explicit operator double(Fixed8 a)
{
    return (double)a._numerator / (double)DENOMINATOR;
}

public override string ToString()
{
    return ((double)this).ToString();
}

例子:

var a = new Fixed8(7);
var b = new Fixed8(1.7);

Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(a / b);

输出:

7
1.69999998807907
4.11764705181122
于 2012-10-13T19:53:01.680 回答
0
public long Division()
{
    long result = _numerator / DENOMINATOR;
    return result;
}
于 2012-10-13T19:32:14.823 回答
0

使用 aSystem.Numerics.BigInteger很好。但是在这种特定情况下, aSystem.Decimal实际上具有足够的精度。所以这是我的建议:

 public static Fixed8 operator /(Fixed8 a, Fixed8 b)
 {
   decimal resultNumerator = (decimal)a._numerator * DENOMINATOR / b._numerator;
   return new Fixed8 { _numerator = Convert.ToInt64(resultNumerator) };
 }
于 2012-10-13T20:17:15.637 回答