在Swift中乘以携带

时间:2015-01-28 07:27:45

标签: ios swift

以下代码段是multiply-with-carry algorithm的直接翻译,可以在各个地方找到(我以this one作为参考)。

public class MultiplyWithCarryRandomGenerator
{

 struct Static {
    static var m_w:UInt = 521748629
    static var m_z:UInt = 762436069
 }

 class var m_w:UInt{get{return Static.m_w } set{Static.m_w = newValue}};
 class var m_z:UInt{get{return Static.m_z } set{Static.m_z = newValue}};

 private class func GetUint()->UInt
 {
    m_z = 36969 * (m_z & 65535) + (m_z >> 16);
    m_w = 18000 * (m_w & 65535) + (m_w >> 16);
    return (m_z << 16) + m_w;
 }

 public class func GetUniform()->Double
 {
    return   ((Double(GetUint()) + 1.0) * 2.32830643545449e-10);
 }
}

在XCode游乐场内,均匀分布保持介于0到40K之间,而它应该在区间(0,1)中。 我的代码或iOS工具,操场上是否有明显的错误??

Sample uniform array plot

1 个答案:

答案 0 :(得分:2)

导致此问题的C#(该示例的语言)和Swift之间存在两个差异。第一个是C#uint是一个32位无符号整数,而Swift中的UInt是一个无符号整数,与它正在执行的系统的体系结构相匹配,这意味着今天大多数情况UInt是64位无符号整数。由于代码中的所有常量都面向32位,因此只需将所有UInt声明更改为UInt32,然后再将其设置为中途。

第二个区别是当使用无符号整数时,加法操作在C#中自动溢出,而在Swift中溢出崩溃。您还没有看到问题,因为您正在使用具有64位数据类型的32位常量,但在切换到UInt32之后,您将开始崩溃溢出行:

return (m_z << 16) + m_w;

Swift提供了一组备用运算符,前缀为&,默认允许在该行中使用&+溢出来解决问题:

return (m_z << 16) &+ m_w;

现在你得到了你希望的图表:

enter image description here