Swift 中的进位乘法
Multiply-with-carry in Swift
以下代码片段直接翻译multiply-with-carry algorithm which can be found in various places (I took 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、游乐场...的人工产物?
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;
现在你得到了你想要的图表:
以下代码片段直接翻译multiply-with-carry algorithm which can be found in various places (I took 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、游乐场...的人工产物?
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;
现在你得到了你想要的图表: