这两种方法是确定的吗?

本文关键字:两种 方法 | 更新日期: 2023-09-27 18:06:05

这两个c#方法是完全确定的吗-因为它们在所有平台上产生相同的结果?

Fix64struct, rawValue字段类型为longONE是这样定义的常量const long ONE = 1L << 32;

函数1 :

public static explicit operator Fix64(double value) {
            return new Fix64((long)(value * ONE));
        }

Fix64构造函数接受long值,只是将其分配给rawValue字段。这里的运算是乘法。ONE将被转换为double。然后两个double值相乘。根据c#规范,这可以以更高的精度发生。然后用long强制转换截断结果。如果在不同的平台上使用不同的乘法精度,那么所得到的long值的最低有效位是否有可能不同?或者这种方法是完全确定的?

函数2 :

public static explicit operator double(Fix64 value) {
        return (double)value.rawValue / ONE;
    }

这与第一个示例类似。这里我们在double之间进行除法运算,然后返回结果为double。是否有可能,如果我们将此方法的结果与另一个double进行比较,编译器可以在比较期间留下更高精度的double ?

另一个强制类型转换能确保这个比较总是确定性的吗?

(double)((double)value.rawValue / ONE)

编辑:这两个函数在FixedPoint64类型和double类型之间转换。这里的论点是,通过只执行单个操作,我们没有使用扩展的中间浮点值进行额外的操作。因此,通过立即截断结果到标准精度,计算应该是确定的。或者这种逻辑有什么缺陷吗?

这两种方法是确定的吗?

答案是肯定的,两者都是确定性的。我从库的作者那里得到的解释是:

对于乘法/除法,如果其中一个FP数是两个数的幂(2^x),在计算过程中有效/尾数不会改变。只有指数会改变(点会移动)。所以舍入永远不会发生。结果将是确定的。

示例:像2^32这样的数字表示为(exponent: 32,尾数:1)。如果我们将它与另一个浮点数(exp, man)相乘,结果是(exp + 32, man * 1)。对于除法,结果是(expo - 32, man * 1)。尾数乘以1不会改变尾数,所以它有多少位无关。