这两种方法是否具有确定性?

时间:2016-09-07 09:24:06

标签: c# .net floating-point deterministic

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

Fix64 struct 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类型之间转换。这里的论点是,通过仅执行单个操作,我们不使用扩展中间浮点值进行其他操作。因此,通过立即将结果截断为标准精度,计算应该是确定性的。或者这个逻辑有什么缺陷吗?

1 个答案:

答案 0 :(得分:0)

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

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

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