算法中的精确时间计数器的应用

算法设计:案例分析1(计数器控制的循环) 举个例子:一个有10名学生的班级进行了一次测试,每个学生的成绩(0·····100范围内的整数)已知。确定本次测验中的班级平均成绩。       首先,用伪码列出要执行的动作并指定它们的执行顺序。我们用计数器控制的循环每次输入一个成绩。用一个变量控制一组语句执行的次数。 ······························································ 阅读详情

算法中的精确时间计数器的应用

流浪狗 2006.3

   评价一个算法的好坏,在运行时所消耗的时间是一个很重要的参数,可以反应出该算法的时间复杂度。要测试一个程序运行时所消耗的时间,我们可以写出很多种算法。很多编译器都提供了相关的时间函数库,还有系统的API等等。但是,我们会发现这些函数在程序中根本本能得到满意的结果。有时候设计得很好的算法,或者很小的算法,在运行的时候非常快,在1ms以内,这时候要测试这个算法所消耗的时间就是一件不容易的事情。

  在头文件time.h中有个函数clock(),返回clock_t的类型,可以通过两次调用clock函数,来确定时间间隔。API中有一个函数叫做GetTickCount的函数,可以得到当前计算机运行的时间,它返回一个DWORD值。在程序短之前加入一句DWORD t=GetTickCount();在程序段后加入t=GetTickCount()-t,则t的结果就是此程序段运行的时间。但是我们会发现很多程序段的结果输出都是0ms,所以我们需要比这个精度更高的函数。有没有这样的函数呢,通过查询MSDN,发现有两个函数满足要求,QueryPerformanceFrequency和QueryPerformanceCounter,它可以精确到0.5微秒,具体说明可以参见MSDN。为了方便我们以后在对算法时间的计算,我们把他封装成一个计时器类:

#include <windows.h>
#include<iostream.h>

using namespace std;

class TimeTake{
public:
 TimeTake():dCount(0)
 {
  // 获得计数器的时钟频率
  QueryPerformanceFrequency(&lPoint);
  dFreq=(double)lPoint.QuadPart;
 }
 ~TimeTake()
 {  
 }
 void print()
 {
  cout<<dCount<<" ms elapse in the  algothim!"<<endl;
 }
 void start()
 {
  //第一次取计数器的值
  QueryPerformanceCounter(&lPoint);
  lPart=lPoint.QuadPart;
 }
 void end()
 {
  //再一次取计数器的值并计算中间的时间间隔,表示成ms
  QueryPerformanceCounter(&lPoint);
  dCount=(double(lPoint.QuadPart-lPart)/dFreq)*1000;
 }
private:
 LARGE_INTEGER lPoint;
 LONGLONG lPart;
 double  dFreq, dCount; 
};

 我们可以写三个算法,用其对他们进行测试,下面几个算法都是求最大公约数的问题,第二个是第一个算法的改进,第三个是求使得a*m+b*n=d的最大公因数,详细算法如下:

DWORD mode1(DWORD m,DWORD n)
{
 int r=m%n;
 while(r!=0)
 {
  m=n;
  n=r;
  r=m%n;
 }
 return n;

}
DWORD mode2(DWORD m,DWORD n)
{
 DWORD r,result;
 while(1)
 {
  r=m%n;
  if(r==0)
  {
   result=n;
   break;
  }

  m=n%r;
  if(m==0)
  {
   result=r;
   break;
  }

  n=r%m;
  if(n==0)
  {
   result=m;
   break;
  }

 }
 return result;
}

//求接a,b使得am+bn=d,d为最大公倍数
DWORD mode(DWORD m,DWORD n,int& a,int& b)
{
 int al,bl; //求解al,bl使得al*m+bl*n=c;
 DWORD c,d,q,r,t;
 c=m;
 d=n;
 a=bl=0;
 b=al=1;
 while(1)
 {
  q=c/d;
  r=c%d;
  if(r==0)
   break;
  else
  {
   c=d; d=r;
   t=al;
   al=a;
   a=t-q*a;
   t=bl;
   bl=b;
   b=t-q*b;
  }
 }
 return d;

}

 然后编写主程序进行测试:

int _tmain(int argc, _TCHAR* argv[])


{

 TimeTake tk;
 int a,b;
 DWORD m,n,d1,d2;
 cout<<"please input m and n"<<endl;
 cin>>m>>n;
 while(n==0)
 {
  cout<<"n can't be zero,please input n again!"<<endl;
  cin>>n;
 }

 tk.start();
 d1=mode1(m,n);
 cout<<"the mode 1's result is "<<d1<<endl;
 tk.end();
 tk.print();

 tk.start();
 d2=mode2(m,n);
 cout<<"the mode 2's result is "<<d2<<endl;
 tk.end();
 tk.print();

 tk.start();
 d2=mode(m,n,a,b);
 cout<<"the result is "<<a;
 if(b>=0)
  cout<<"*m+"<<b<<"*n="<<d2<<endl;
 else
  cout<<"*m"<<b<<"*n="<<d2<<endl;
 tk.end();
 tk.print();

 return 0;
}

 输出结果如下:

please input m and n
150
456
the mode 1's result is 6
1.9469 ms elapse in the  algothim!
the mode 2's result is 6
1.23787 ms elapse in the  algothim!
the result is -3*m+1*n=6
1.18842 ms elapse in the  algothim!
Press any key to continue

通过多组数据的输入,我们可以肯定的是第二种算法比第一种算法用的时间少,因为第二种算法避免了第一种算法的重复赋值。但是第三种算法与前两种算法相比,体现出时间的不确定性,有时候时间处于前两种算法之间,有时候又比前两种都少。从表面上来看,第三种算法比前两种做的事情都要多,但是为什么他用的时间最少呢?

sentinel 滑动时间窗口算法 sentinel 滑动时间窗口的算法 为什么要用滑动时间窗口算法? 原始的计数器算法 计数器算法的实现比较简单,在启动时候,设置一个初始的时间,然后设置一段时间interval作为滑动时间,如果请求方法时候进来的时间在这个区间内,并且没有超过控制值,就return true。 /** * 最简单的计数器限流算法 */ public class Counter { public long timeStamp = System.currentTimeMillis(); // 当前时间 public i 阅读详情

相关推荐

精度不够,滑动时间来凑「限流算法第二把法器:滑动时间窗口算法

2)在main方法中,我们通过开启一个线程来执行我们的doCheck()方法,由于doCheck()方法是while(true),所以会一直执行,sleep的时间刚好是每个时间间隔值,那么就会不断刷新LinkedList中的值。当在系统刚刚启动的时候,系统很多资源都未分配完成,瞬间来了n个请求,如果使用滑动窗口算法的话,那么只有达到了QPS控制阈值,才会触发限流机制,那么这样针对系统刚启动资源未分配的情况,就无法防止系统瘫痪了。回顾一下上面的计数器算法,我们可以发现,计数器算法其实就是滑动窗口算法。...

Park33的博客 1857

算法 计数器_频率计数器是什么以及它们如何帮助您更好地求解算法

算法 计数器Frequency Counters — how they can help decrease time and space complexity in algorithms 频率计数器-如何帮助减少算法中的时间和空间复杂度 In the middle of interviews and practicing never-ending algorithms, I’ve started...

weixin_26755331的博客 318

剖析常见的限流算法计数器法、漏桶和令牌桶算法

常见的限流算法1. 计数器法2. 漏桶和令牌桶算法3.Spring Cloud Gateway限流 对于业务系统来说高并发就是支撑「海量用户请求」,QPS 会是平时的几百倍甚至更高。 如果不考虑高并发的情况,即使业务系统平时运行得好好的,并发量一旦增加就会频繁出现各种诡异的业务问题,比如,在电商业务中,可能会出现用户订单丢失、库存扣减异常、超卖等问题。 限流是服务降级的一种手段,顾名思义,通过限制系统的流量,从而实现保护系统的目的。 合理的限流配置,需要了解系统的吞吐量,所以,限流一般需要结合容量规划和

Justdoforever的博客 1195

python时间复杂度的计算

大O推导法: 用常数1取代运行时间中的所有加法常数 在修改后的运行函数中,只保留最高阶项 如果最高阶项存在且不是1,则去除与这个项相乘的常数 常见情况: 1、常数阶 运行四次,f(n)=4,常数,时间复杂度为O(1) 2、线性阶 线性阶的循环结构会复杂一些,要确定某个算法的阶次,需要确定特定语句或某个语句集运行的次数。因此要分析算法的复杂度,关键是要分析循环结构的运行情况。 ...

koyee的博客 4436

最易懂详细的算法时间复杂度讲解

https://blog.csdn.net/qq_41523096/article/details/82142747

以笑对世~的博客 3200

计时器计算小时、分钟、秒数

一般情况下,在App中开启一个计时的时候都是以秒为单位进行倒计时或者正计时,通过总共的秒数来计算小时:分钟:秒。 思路 假如当前计时器共计3780秒,那么 NSInteger second = 3780; //整小时 NSInteger hour = second/3600; NSLog(@&amp;quot;%ld&amp;quot;,(long)hour); //整分钟 NSInteger minute...

竹毛言己 1万+

限流算法计数器、滑动时间窗口、漏斗、令牌)原理以及代码实现

什么是限流?限流 限流 就是限制流量。在高并发、高流量的场景中我们需要把限流做好,防止突发的流量、恶意的攻击等大量请求的冲击带来不必要的影响,保证业务系统的正常运行。如何限流?首先我们需要知道限流的基本思路,其次需要知道限流的几种实现方式(这里我们叫限流算法)。限流的基本思路就是在一个单位时间内流量超过某个阈值后被拒绝或限制。目前常见的限流算法计数器(固定时间窗口)算法、滑动时间窗口算法、漏斗算法、令牌算法

二蛋的博客 5163

【限流算法】java实现滑动时间窗口算法

本文实现了一种基于java的滑动时间窗口计数器算法 滑动时间窗口计数器算法思想:针对固定时间算法会在临界点存在瞬间大流量冲击的场景,滑动时间窗口计数器算法应运而生。它将时间窗口划分为更小的时间片段,每过一个时间片段,我们的时间窗口就会往右滑动一格,每个时间片段都有独立的计数器。我们在计算整个时间窗口内的请求总数时会累加所有的时间片段内的计数器时间窗口划分的越细,那么滑动窗口的滚动就越平滑,限流...

DreamSeeker 1万+

【sentinel】滑动时间窗口算法在Sentinel中的应用

上面会出现突刺的问题其实就在于固定窗口算法的窗口时间跨度太大,且是固定不变的,为了解决突刺的问题,我们就有了滑动窗口计数器限流算法。划分多个小的时间段,各时间段各自进行计数。根据当前时间,动态往前滑动来计算时间窗口范围,合并计算总数。可以看到,每次时间往后,窗口也会动态往后滑动,从而丢弃一些更早期的计数数据,从而实现总体计数的平稳过度。当滑动窗口划分的格子越多,那么滑动窗口的滑动就越平滑,限流的统计就会越精确。事实上,固定窗口算法就是只划分成一个格子的滑动窗口算法

morris 1577

【限流算法计数器、漏桶、令牌桶、滑动时间窗口

限流算法总结:文本介绍了计数器、漏桶、令牌桶、滑动时间窗口的区别和使用场景

qq_40782372的博客 454

限流之计数器算法

一点睛 发生过载的原因主要是缓冲区满,导致处理的请求超时。所以限制流量,尽早拒绝过载状态的请求,能够保证服务尽量处理负载过程中的请求。 限流的主要方法有下面四种: 计数器算法 滑动窗口算法 漏桶算法 令牌桶算法 本篇介绍计数器算法。 二算法 计数器算法是在一定的时间间隔里,记录请求次数,当请求次数超过该时间限制时,就把计数器清零,然后重新计算。当请求次数超过间隔内的最大次数时,拒绝访问。 例如:一个接口每分钟允许访问100次。实现方式如下: 1设置一...

实践求真知 2594

【限流算法】java实现redis分布式时间窗口计数器算法

本文实现一种基于java的分布式固定时间窗口计数器算法 //每次请求进来,查询一下当前的计数值,如果超出请求数阈值,则拒绝请求,返回系统繁忙提示 private long limitFlow(String key) { //Setnx(SET if Not eXists) 命令在指定的 key 不存在时,为 key 设置指定的值。设置成功返回1,设置失败返回0 ...

DreamSeeker 3881

时间算法在定时任务与延时消息中的应用

一、延时任务中的时间轮 1.1 背景 项目开发中,我们经常会遇到这些场景: 1.小程序商城用户下单,30分钟订单未付款自动取消。 2.秒杀活动开始前15分钟对设置了秒杀提醒的用户进行推送。 3.用户成功秒杀到商品,5分钟未提交订单退回商品。 上述场景传统的解决方案一般是采用定时任务执行,通过设置定时任务的执行间隔,定时进行检测执行。 参考:分布式定时任务调度框架实践 1.2 缺陷 然而,定时任务的方案会存在以下不足: 1.触发时间和频率不好设置。 2.不能满足实时性要求高的场景。 3.会导致任务对应业

CodeMavs的博客 1756

toBeBetterJavaer API限流:计数器算法实现

在高并发场景下,API接口面临着大量请求的冲击,可能导致系统过载、响应缓慢甚至崩溃。为了保护系统的稳定性和可用性,API限流成为必不可少的一环。计数器算法作为一种简单有效的限流方案,被广泛应用于各类系统中。本文将详细介绍计数器算法的原理、实现方式以及在实际项目中的应用。 ## 计数器算法原理 计数器算法是一种基于时间窗口的限流算法,其核心思想是在固定的时间窗口内统计请求数量,如果请求数量超过预

gitblog_00697的博客 1066

解读计数器算法:原理、Java实现与优劣分析

计数器算法的基本原理是通过一个计数器来记录事件的发生次数。每当一个特定的事件发生时,计数器的值就会增加一。当需要检查这个事件发生的次数时,只需要查看计数器的当前值即可。这种方法简单直观,易于理解和实现。想象一下,在超市的收银台,每当有一个顾客完成结账,收银员就会在计数器上按一次。这样,店主就可以通过查看计数器的值,知道一天中有多少顾客在这个收银台完成了结账。这就是计数器算法的一个生活中的例子。计数器算法有很多实际的应用场景,比如网络流量控制、系统性能监控、用户行为统计等。

万猫学社 1588

java之限流算法(计数器算法、令牌算法、漏桶算法

1 计数器算法(单机限流) 具体的实现可以是这样的:对于每次服务调用,可以通过AtomicLong#incrementAndGet()方法来给计数器加1并返回最新值,通过这个最新值和阈值进行比较。 这种实现方式,相信大家都知道有一个弊端:如果我在单位时间1s内的前10ms,已经通过了100个请求,那后面的990ms,只能眼巴巴的把请求拒绝,我们把这种现象称为“突刺现象” 具体业务代码: publi...

坚持者的博客 1277

精度不够,滑动时间来凑「限流算法第二把法器:滑动时间窗口算法」- 第301篇

相关历史文章(阅读本文之前,您可能需要先看下之前的系列????) 为数据可视化赋能SpringBootAdmin-第297篇 超实用的康奈尔笔记法 「定制SpringBootAdminUI的页面」-第298篇 国内最全的SpringBoot系列之三 版本号命名的前世今生-值得收藏-第299篇 「世界上最好的学习法:费曼学习法」 高并发,不怕不怕「限流算法第一把法...

悟纤学院 2万+
上一篇: 类似QQ界面的实现
下一篇: A*m+B*n=D问题的数学推导求解
jamiandy
博客等级 码龄22年 0粉丝 4原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值