C# 浮点的乘除、整形的乘除和位操作
〇、前言
系统自带计时器 -System.Diagnostics.StopWatch- 的使用
System.Diagnostics.StopWatch 的基本使用方法
//引用命名空间
using System.Diagnostics;
//创建一个计时器
Stopwatch timer = new Stopwatch();
//计时开始
timer.Start();
//计时结束
timer.Stop();
//转换成秒形式
decimal second = timer.Elapsed.Ticks * 0.000_000_1m;
//如果要转换成微秒形式:
decimal microSecond = timer.Elapsed.Ticks * 0.1m;
//在输出面板输出代码所用时间, ":F4"是保留4位小数的意思
Debug.Log($"Takes {second:F4} second");
知识区: 微秒
提示: 接下来所有测试都以以下代码为标准代码块(更详细的见测试代码运行所用时间(一)),并在测试不同内容时进行不同修改:
...
// ==!==(修改区 0) 修改 count 大小
private int count = 100_000;
...
private void OnClicked()
{
// ==!==(修改区 1) 最初初始化代码块
...
for (int testIndex = -1; testIndex < (n/*测试实验个数(预热和对比区除外)*/ + 1) * 3; ++testIndex)
{
// ==!==(修改区 2) 每次初始化代码块
...
int index = Mathf.FloorToInt(testIndex * 0.334f);
Stopwatch timer = new Stopwatch();
timer.Start();
switch (index)//每个测试 3 次
{
//传统"预热"
case -1:
break;
// case 0 一般都为普通循环(对比区)
case 0:
for (int i = 0; i < count; ++i) { }
break;
// ==!==(修改区 3) 其他测试代码块
case 1:
...
break;
...
}
timer.Stop();
UnityEngine.Debug.Log($"{index}: Takes -{timer.Elapsed.Ticks}- ticks");
// ==!==(修改区 4) 结束后进行其余操作的代码块
...
}
}
一、浮点的乘除
修改代码片:
//(修改区 0)
public double testDouble = 114.514;
public float testFloat = 114.514;
public int testMul = 2;
//(修改区 2)
double tempDouble;
float tempFloat;
其中 测试实验个数 n = 4
//(修改区 3)
//float 除
case 1:
for (int i = 0; i < count; ++i)
{
tempFloat = testFloat / testMul;
}
break;
//float 乘
case 2:
float tempMul_float = 1 / testMul;
for (int i = 0; i < count; ++i)
{
tempFloat = testFloat * tempMul_float;
}
break;
//double 除
case 3:
for (int i = 0; i < count; ++i)
{
tempDouble = testDouble / testMul;
}
break;
//double 乘
case 4:
double tempMul_double = 1 / testMul;
for (int i = 0; i < count; ++i)
{
tempDouble = testDouble * tempMul_double;
}
break;
为了能够在短时间内把 testMul 所有情况遍历过去,本博客主在开始时循环调用 OnClicked() 方法:
其中 testMul 与实验数据有关
for (testMul = 2; testMul <= 7; ++testMul)
{
OnClicked();
}
在Unity中多次测试后取稳定值,记录实验数据:
testMul 的值\实验编号 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
2 | 3126 | 2324 | 1675 | 2366 |
3 | 3207 | 2304 | 1673 | 2327 |
4 | 3130 | 2294 | 1672 | 2310 |
5 | 3208 | 2208 | 1676 | 2239 |
6 | 3121 | 2334 | 1671 | 2289 |
7 | 3210 | 2341 | 1681 | 2213 |
由上述实验数据可得:
对于单精度浮点数的简单除法,可以使用乘以倒数的方法减少时间消耗;比如
num / 2
可以改写为num * 0.5f
;
而对于双精度浮点数,最好直接用除。
二、int 的乘除与位移
修改以下代码片,并进行测试:
//(修改区 0)
public int testInt = 114514;
public int testMul = 2;
其中 测试实验个数 n = 4
//(修改区 2) 计算testMul的位数,如果不是2的指数,则不进行位移操作
int tempInt;
int tempMul_int = testMul;
int digit = 0;
bool fullDigit = true;
while (tempMul_int != 1)
{
if (tempMul_int / 2 * 2 == tempMul_int )
{
++digit;
tempMul_int /= 2;
}
else
{
fullDigit = false;
break;
}
}
//(修改区 3)
//int 乘
case 1:
for (int i = 0; i < count; ++i)
{
tempInt = testInt * testMul;
}
break;
//int 左移
case 2:
if(fullDigit)
for (int i = 0; i < count; ++i)
{
tempInt = testInt << tempMul_int;
}
else
continue;
break;
//int 除
case 3:
for (int i = 0; i < count; ++i)
{
tempInt = testInt / testMul;
}
break;
//int 位操作
case 4:
if(fullDigit)
for (int i = 0; i < count; ++i)
{
tempInt = testInt >> tempMul_int;
}
else
{
if (testIndex == max - 1) return;
continue;
}
break;
同上述浮点数乘除的代码,测试 int位移时间消耗 也要在短时间内把 testMul 所有情况遍历过去:
for (testMul = 2; testMul <= 7; ++testMul)
{
OnClicked();
}
最后在Unity中多次测试后取稳定值,记录实验数据:
testMul 的值\实验编号 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
2 | 1285 | 1775 | 2057 | 1786 |
3 | 1286 | / | 2056 | / |
4 | 1286 | 1679 | 2057 | 1736 |
5 | 1223 | / | 1957 | / |
6 | 1223 | / | 1957 | / |
7 | 1223 | / | 1957 | / |
8 | 1286 | 1777 | 2057 | 1707 |
最后得出实验结论:
对于 int :
如果进行乘运算,用左移是画蛇添足的;
如果进行除运算,如果除数是2的指数倍则右移操作会稍稍提升运行速度;
常用于把num / 2
改成num>>1
。
新人博主,请大家多多光照~~如果有什么不正确或不足的地方请在评论区积极指出哟,一起学习一起进步~