我是 Dart 编程语言的新手,我转向我常用的测试 FizzBuzz 来检查该语言。目前,我有这个相对
if
重的示例,速度相当慢。在我的 MacBook Pro 上,只要删除一个 if 语句,执行时间就会从 36 秒缩短到 25 秒,循环次数为 5000000 次。我想知道如何进一步优化它。
void main() {
for (int i = 0; i < 5000000; i++) {
var num = i + 1;
if (num % 15 == 0) {
print('FizzBuzz');
continue;
}
if (num % 5 == 0) {
print('Buzz');
continue;
}
if (num % 3 == 0) {
print('Fizz');
continue;
}
print(num);
}
}
我尝试将其全部包装在
switch
语句中,如下所示,但它没有编译为JS,并且DartPad给出错误Type 'int' of the switch expression isn't assignable to the type 'bool' of case expressions.
void main() {
for (int i = 0; i < 5000000; i++) {
var num = i + 1;
switch (num) {
case (num % 15 == 0):
print('FizzBuzz');
break;
case (num % 5 == 0):
print('Buzz');
break;
case (num % 3 == 0):
print('Fizz');
break;
default:
print(num);
}
}
}
提前谢谢您。
num
是内置类型的类型(int
和double
的共同超类型),而且case ...:
表达式需要是常量,因此不能基于非常量值进行计算。
我认为使用
if
是最好的选择。
在进行这样的性能测试时,打印到控制台变得非常重要。使用您的代码,您最重要的是在这里测试打印速度。条件语句和增量只是运行时间的一小部分。
尝试以下操作:
import 'dart:async';
main(){
// mark the start of go
var begin = DateTime.now();
go();
//mark the time that go completes and goZoned begins
var midpoint = DateTime.now();
goZoned();
// mark the end of goZoned
var end = DateTime.now();
print("done:\n$begin\n$midpoint\n$end");
}
// This function runs the go function, but short-circuits any calls to print
// with a no-op
void goZoned() {
runZoned(() {
go();
}, zoneSpecification: new ZoneSpecification(
print: (Zone self, ZoneDelegate parent, Zone zone, String line) {}
)
);
}
void go(){
for (int i = 0; i < 5000000; i++) {
var num = i + 1;
if (num % 15 == 0) {
print('FizzBuzz');
continue;
}
if (num % 5 == 0) {
print('Buzz');
continue;
}
if (num % 3 == 0) {
print('Fizz');
continue;
}
print(num);
}
}
我机器上的结果是
done:
2018-09-10 10:33:23.012086
2018-09-10 10:33:33.407191
2018-09-10 10:33:33.827196
您可以看到,有 print 语句的执行花费了 10 多秒,但没有 print 语句的执行时间略多于三分之一秒。
(挂墙时间仍然是一种非常粗略的测量运行时间的方法,但在这里可以发挥作用)
FizzBuzz 可以在不使用 if 语句的情况下解决:
void main() {
fizzBuzz(100).forEach(print);
}
Iterable<String> fizzBuzz(int limit) sync* {
for (int i = 1; i <= limit; i++) {
yield i % 3 == 0 && i % 5 == 0
? "FizzBuzz"
: i % 3 == 0
? "Fizz"
: i % 5 == 0
? "Buzz"
: i.toString();
}
}