Count total set bits in all numbers from 1 to n

本文介绍了一种高效算法来计算从1到n的所有整数中二进制表示的1的总数,并通过递归方式解决了该问题。对于特殊形式的n,给出了直接计算公式。

reference: 

http://www.geeksforgeeks.org/count-total-set-bits-in-all-numbers-from-1-to-n/


Problem Definition:

Given a positive integer n, count the total number of set bits in binary representation of all numbers from 1 to n.

Examples:

Input: n = 3
Output:  4

Input: n = 6
Output: 9


Solution:

If the input number is of the form 2^b -1 e.g., 1,3,7,15.. etc, the number of set bits is b * 2^(b-1). This is because for all the numbers 0 to (2^b)-1, if you complement and flip the list you end up with the same list (half the bits are on, half off).

If the number does not have all set bits, then some position m is the position of leftmost set bit. The number of set bits in that position is n – (1 << m) + 1. The remaining set bits are in two parts:

1) The bits in the (m-1) positions down to the point where the leftmost bit becomes 0, and
2) The 2^(m-1) numbers below that point, which is the closed form above.

An easy way to look at it is to consider the number 6:

0|0 0
0|0 1
0|1 0
0|1 1
-|–
1|0 0
1|0 1
1|1 0

The leftmost set bit is in position 2 (positions are considered starting from 0). If we mask that off what remains is 2 (the "1 0" in the right part of the last row.) So the number of bits in the 2nd position (the lower left box) is 3 (that is, 2 + 1). The set bits from 0-3 (the upper right box above) is 2*2^(2-1) = 4. The box in the lower right is the remaining bits we haven't yet counted, and is the number of set bits for all the numbers up to 2 (the value of the last entry in the lower right box) which can be figured recursively.


Code:

// Returns count of set bits present in all numbers from 1 to n
unsigned int countSetBits(unsigned int n)
{
   // Get the position of leftmost set bit in n. This will be
   // used as an upper bound for next set bit function
   int m = getLeftmostBit (n);
 
   // Use the position
   return _countSetBits (n, m);
}
 
unsigned int _countSetBits(unsigned int n, int m)
{
    // Base Case: if n is 0, then set bit count is 0
    if (n == 0)
       return 0;
 
    /* get position of next leftmost set bit */
    m = getNextLeftmostBit(n, m);
 
    // If n is of the form 2^x-1, i.e., if n is like 1, 3, 7, 15, 31,.. etc, 
    // then we are done. 
    // Since positions are considered starting from 0, 1 is added to m
    if (n == ((unsigned int)1<<(m+1))-1)
        return (unsigned int)(m+1)*(1<<m);
 
    // update n for next recursive call
    n = n - (1<<m);
    return (n+1) + countSetBits(n) + m*(1<<(m-1));
}


# 创建一个全局的循环队列以及全局共享变量 from queue import Queue global_data=[] global_queue = Queue() from datetime import datetime from threading import Thread import serial, re, math from flask import Flask, render_template, request, jsonify from pyecharts import options as opts from pyecharts.charts import Line import matplotlib.pyplot as plt import numpy from kalman5 import * from wifilib import * import mysql.connector from random import randrange from flask import Flask, render_template from pyecharts import options as opts from pyecharts.charts import Line app = Flask(__name__, static_folder="templates") app.config['MYSQL_HOST'] = 'localhost' # MySQL 主机名 app.config['MYSQL_USER'] = 'root' # MySQL 用户名 app.config['MYSQL_PASSWORD'] = '123123' # MySQL 密码 app.config['MYSQL_DB'] = 'csi' # MySQL 数据库名 def get_db_connection(): connection = mysql.connector.connect( host=app.config['MYSQL_HOST'], user=app.config['MYSQL_USER'], password=app.config['MYSQL_PASSWORD'], database=app.config['MYSQL_DB'], ) return connection # 返回的是数据库链接对象 def Line_base(index) -> Line: # index = int(index) # path = r'csi9.dat' # bf = read_bf_file_new(path,index) # csi_list = list(map(get_scale_csi, bf)) # print("test") # print(csi_list) # csi_np = (np.array(csi_list)) # csi_amp = np.abs(csi_np) # csi_total = numpy.empty(csi_amp[:, 0, 0, 25].shape) # csi_total_a = numpy.empty(csi_amp[:, 0, 0, 25].shape) # for i in range(6): # csi_total = csi_total + csi_amp[:, 0, 0, i + 15] # csi_total = csi_amp[:, 0, 0, 15] # csi_total_a = kalman_filter1(csi_amp[:, 0, 0, 15]) global_data.clear() for i in range(51): global_data.append(global_queue.get()) print(global_data) csi_total_a = kalman_filter1(global_data) csi_total_a = csi_total_a[3:51] list2 = [str(i) for i in range(0, 48)] c = ( Line() .add_xaxis(list2) # .add_yaxis("波形1", csi_total[0:50],is_smooth='spline',is_symbol_show=False,color='blue') .add_yaxis("波形1", csi_total_a[0:48], is_smooth='spline', is_symbol_show=False, color='blue') .set_global_opts(title_opts=opts.TitleOpts(title="入侵检测系统", subtitle="实时波形检测"), yaxis_opts=opts.AxisOpts(max_=80, min_=0) ) ) return c @app.route("/") def index(): return render_template("index.html") @app.route("/LineChart") def get_Line_chart(): index = request.args.get('index') c = Line_base(index) return c.dump_options_with_quotes() @app.route("/getCount") def getCountAndIn(): index = request.args.get("index2") # print(index) state = getCountAndIN(index) # 返回一个包含入侵事件计数的JSON响应 return jsonify({'count': state}) @app.route('/get_alarm_history', methods=['GET']) def get_alarm_history(): try: connection = get_db_connection() cursor = connection.cursor() cursor.execute("SELECT date, type, description FROM alarm_history ORDER BY date DESC") history_data = cursor.fetchall() cursor.close() return jsonify({'data1': history_data}) except Exception as e: return jsonify({'error': str(e)}) import matplotlib.pyplot as plt import numpy import threading from wifilib import * from kalman5 import * from fancha import * import time import smtplib from email.mime.text import MIMEText from email.utils import formataddr plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False my_sender = '3284306656@qq.com' # 发件人邮箱账号 my_pass = 'bmjvijanuogzchbc' # 发件人邮箱授权码 my_user = '3377646378@qq.com' # 收件人邮箱账号,我这边发送给自己 def mail(): ret = True try: msg = MIMEText('有人入侵请注意!!!!!!', 'plain', 'utf-8') msg['From'] = formataddr(["XXX", my_sender]) msg['To'] = formataddr(["XXX", my_user]) msg['Subject'] = "测试报告" server = smtplib.SMTP_SSL("smtp.qq.com", 465) # 发件人邮箱中的SMTP服务器,端口是25 server.login(my_sender, my_pass) server.sendmail(my_sender, [my_user, ], msg.as_string()) # server.quit() except Exception: ret = False # print(1) # global_data def getCountAndIN(offset) -> object: # path = r'csi8.dat' # offset = int(offset) # date = numpy.empty([1, 7]) # bf = read_bf_file_new2(path, offset) # csi_list = list(map(get_scale_csi, bf)) # csi_np = (np.array(csi_list)) # csi_amp = np.abs(csi_np) # csi_total = numpy.empty(csi_amp[:, 0, 0, 8].shape) # for i in range(6): # csi_total = csi_total + csi_amp[:, 0, 0, i] # date = kalman_filter1(csi_amp[:, 0, 0, 8]) # print("test_data",date) data = kalman_filter1(global_data) data = data[3:50] # print(data) print(dynamic_variance1(data)) if detect_intrusion(dynamic_variance1(data)) == "intrusion": intrusion_date = datetime.now() intrusion_type = "无源入侵" intrusion_description = "有人入侵您的家" connection = get_db_connection() cursor = connection.cursor() sql = "INSERT INTO alarm_history (date, type, description) VALUES (%s, %s, %s)" cursor.execute(sql, (intrusion_date, intrusion_type, intrusion_description)) connection.commit() cursor.close() connection.close() threading.Thread(target=mail()).start() ##邮箱及授权码请自行配置,在SendMail下 return "intrusion" else: return "nobody" def get_csi_data(port): print("多线程1运行中…………") ser = serial.Serial(port=port, baudrate=921600, bytesize=8, parity='N', stopbits=1, timeout=0.1) pattern = r"\"\[(-?\d+,-?\d+)(,\s*-?\d+,-?\d+)*\]\"" while True: if ser.in_waiting > 0: print('abc') data = ser.readline().decode('utf-8').strip() match = re.search(pattern, data) if match: str_data = match.group(0) # 提取整个匹配项,包括引号 # list_data = str_data[1:-1] # 去掉外面的引号 data_string = str_data[2:-2] # 使用split方法按逗号分割字符串,并使用列表推导式将每个字符串转换为整数 numbers_list = [int(num) for num in data_string.split(',')] tmp_results = [] for i, j in zip(numbers_list[2::2], numbers_list[3::2]): # 将数据添加到结果列表,63个 tmp_results.append(math.sqrt(i * i + j * j)) global_queue.put(variance(tmp_results)) # print(variance(tmp_results)) def variance(list): avg = sum(list) / len(list) sum_number = 0 for i in list: sum_number += (i - avg) ** 2 return round(sum_number / len(list)) # def get_data(): # print("多线程2运行中…………") # while(global_queue.qsize()>=50): # global_data.clear() # for i in range(51): # global_data.append(global_queue.get()) port = "COM3" th1 = Thread(target=get_csi_data, args=(port,)) th1.start() if __name__ == "__main__": try: # th1 = Thread(target=get_csi_data, args=(port,)) # th1.start() app.run() except Exception: input("输入任意字符串结束") th1.join() 这串代码com3接口接收的信息在哪里
06-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值