如何在Swift 2.2中替换复杂的C风格for循环

时间:2016-05-01 18:40:27

标签: swift

对于我开发的无符号整数类型库,我有一个专门的C风格for循环,用于计算存储数值中的有效位。我已经挣扎了一段时间,如何将其转换为Swift 2.2+样式的循环。这是相关代码:

// dx1, dx2, dx3, dx4, dy1, dy2, dy3, dy4 instead of dx, dy
// also you can use proportions to keep them bouncing at the same time
// see below

var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var x = canvas.width/2;
var y = canvas.height/2;
/*var dx = -2;
var dy = 2;*/
var ballRadius = 10;

var canvas2 = document.getElementById("canvas2");
var ctx2 = canvas2.getContext("2d");
var x2 = canvas2.width/2;
var y2 = canvas2.height/2;

var canvas3 = document.getElementById("canvas3");
var ctx3 = canvas3.getContext("2d");
var x3 = canvas3.width/2;
var y3 = canvas3.height/2;

var canvas4 = document.getElementById("canvas4");
var ctx4 = canvas4.getContext("2d");
var x4 = canvas4.width/2;
var y4 = canvas4.height/2;

/***********************************************/
/***********************************************/
/***********************************************/
/***********************************************/
/***********************************************/

var dx1 = 2, dx2 = dx1*canvas2.width/canvas.width, dx3 = dx1*canvas3.width/canvas.width, dx4 = dx1*canvas4.width/canvas.width;
var dy1 = 2, dy2 = dy1*canvas2.height/canvas.height, dy3 = dy1*canvas3.height/canvas.height, dy4 = dy1*canvas4.height/canvas.height;

function drawBalls() {
    ctx.beginPath();
    ctx.arc(x, y, ballRadius, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();

    ctx2.beginPath();
    ctx2.arc(x2, y2, ballRadius, 0, Math.PI*2);
    ctx2.fillStyle = "#0095DD";
    ctx2.fill();
    ctx2.closePath();

    ctx3.beginPath();
    ctx3.arc(x3, y3, ballRadius, 0, Math.PI*2);
    ctx3.fillStyle = "#0095DD";
    ctx3.fill();
    ctx3.closePath();

    ctx4.beginPath();
    ctx4.arc(x4, y4, ballRadius, 0, Math.PI*2);
    ctx4.fillStyle = "#0095DD";
    ctx4.fill();
    ctx4.closePath();
}

function clearCanvases() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
    ctx3.clearRect(0, 0, canvas3.width, canvas3.height);
    ctx4.clearRect(0, 0, canvas4.width, canvas4.height);
}

function changeSpeeds() {
    x += dx1;
    y += dy1;
    x2 += dx2;
    y2 += dy2;
    x3 += dx3;
    y3 += dy3;
    x4 += dx4;
    y4 += dy4;
}

function what(a, b, c, r)
{
    if (a + b > c - r || a + b < r)
    {
        b = -b;
    }
}

function checkForCollisions() {
    what(y, dy1, canvas.height, ballRadius);
    what(x, dx1, canvas.width, ballRadius);
    what(y2, dy2, canvas2.height, ballRadius);
    what(x2, dx2, canvas2.width, ballRadius);
    what(y3, dy3, canvas3.height, ballRadius);
    what(x3, dx3, canvas3.width, ballRadius);
    what(y4, dy4, canvas4.height, ballRadius);
    what(x4, dx4, canvas4.width, ballRadius);
}


// I split the draw function into four functions, named bounceBalls
function bounceBalls()
{
    clearCanvases();  // context.clearRect for each of the four canvases...
    drawBalls();    // drawBall in your code
    changeSpeeds();
    checkForCollisions();    // bouncing against sides
}

var FPS = 60;
window.setInterval(bounceBalls, 1000/FPS);

我确定有多种方法可以解决这个问题,我可以想到一些更冗长的处理方式,但我有兴趣找到一种处理这种情况的简洁方法,我可以重新申请类似的情况。我发现我很少使用C风格的循环,但是当我这样做时,它就像这样一个奇怪的场景,它是处理问题最简洁的方式。

3 个答案:

答案 0 :(得分:5)

最简单的解决方案是使用while循环:

替换此代码:

if bitsToWalk > 0 {
    // Walk significant bits by shifting right until all bits are equal to 0.
    for var bitsLeft = bitsToWalk; bitsLeft > 0; bitsLeft >>= 1 {
        significantBitCount += 1
    }
}

使用以下while循环:

while bitsToWalk > 0 {
    significantBitCount += 1
    bitsToWalk >>= 1
}

答案 1 :(得分:1)

一种选择是使用内置处理器功能:

把:

print "Whats your name?"
    name = gets.to_s
print "What is the address for your listing?"
    appointment_address = gets
print "Square footage?"
    sq_ft = gets.to_i
print "listing price"
    listing_price = gets

# PHOTOGRAPHERS

def tps
    tps = 3.to_i
end

def ryan(sq_ft,tps)
    p sq_ft.to_i * tps.to_i
end

appointment_confirmation = 'Hey, '<< name.to_s.strip << '! Your appointment at ' << appointment_address.to_s.strip << ' will take us about ' << sq_ft*tps << ' to complete.'

p appointment_confirmation.strip

到您的Obj-C桥接标题然后在Swift中:

#import <x86intrin.h>

(当然,您必须使用正确的架构,此功能仅在x86上定义。此解决方案不太便于移植。)

答案 2 :(得分:1)

此函数应计算UInt64值中的有效位数:

import Foundation

func significantBits(n: UInt64) -> Int {
    return Int(ceil(log2(Double(n))))
}

let n: UInt64 = 0xFFFFFFFFFFFFFFFF  //  64 significant bits
let m: UInt64 = 0b11011             //  5 significant bits

print("n has \(significantBits(n)) significant bits.")
print("m has \(significantBits(m)) significant bits.")

和输出:

n has 64 significant bits.
m has 5 significant bits.

您可以用以下内容替换您的代码:

private func calcSigBits(n: UInt64) -> Int {
    return Int(ceil(log2(Double(n))))
}

public var significantBits: Int {
    if self.value.upperBits > 0 {
        return calcSigBits(self.value.upperBits) + 64
    }
    else {
        return calcSigBits(self.value.lowerBits)
    }
}

如果你不想使用log2,你可以使用nhgrif的答案中的循环,但是重构这个循环仍然很好,因为它可以使用UInt64。在概念上是单独的操作,并使您自己的代码更简单。您甚至可以将其添加为extension UInt64 { public var significantBits: Int { var sb = 0 var value = self while value > 0 { sb += 1 value >>= 1 } return sb } } // Rest of your class definition... public var significantBits: Int { if self.value.upperBits > 0 { return self.value.upperBits.significantBits + 64 } else { return self.value.lowerBits.significantBits } } 的扩展程序:

//Helper for sorting by last name
function alphabetize_by_last_name( $bp_user_query ) {
    if ( 'alphabetical-last' == $bp_user_query->query_vars['type'] )
        $bp_user_query->uid_clauses['orderby'] = "ORDER BY substring_index(u.display_name, ' ', -1)";
}
add_action ( 'bp_pre_user_query', 'alphabetize_by_last_name' );