百度百科如下:
程序中的所有數在計算機內存中都是以二進制的形式儲存的。位運算就是直接對整數在內存中的二進制位進行操作
位運算是一種底層的運算,往往比我們普通的運算要快上許多許多
位運算是最高效而且占用內存最少的算法操作,執行效率非常高
位運算操作的是二進制數,會擁有一些二進制的特性,在實際問題可以方便運用
位運算只需較低的空間需求
位運算使用能使程序變得更加簡潔和優美
位運算可以表示一些狀態集合
下面的a和b都是整數類型,則:
含義 | C語言 |
---|---|
按位與 | a & b |
按位或 | a | b |
按位異或 | a ^ b |
按位取反 | ~a |
左移 | a << b |
帶符號右移 | a >> b |
無符號右移 |
C語言中位運算符之間,按優先級順序排列為
優先級 | 符號 |
---|---|
1 | ~ |
2 | <<、>> |
3 | & |
4 | ^ |
5 | | |
6 | &=、^=、|=、<<=、>>= |
本文會以C語言的交互環境來做代碼演示
常見的二進制位的變換操作
判斷奇偶數
對于除0以外的任意數x,使用x&1==1作為邏輯判斷即可
if (x&1==1)
{
}
判斷某個二進制位是否為1
比如第7位, 0x40轉到二進制是0100 0000,代表第7位是1.
if (n&0x40)
{
//TODO:添加你要處理的代碼
}
字節讀取
(x >> 0) & 0x000000ff/* 獲取第0個字節 */
(x >> 8) & 0x000000ff/* 獲取第1個字節 */
(x >> 16) & 0x000000ff/* 獲取第2個字節 */
(x >> 24) & 0x000000ff/* 獲取第3個字節 */
判斷一個數是不是 22 的指數
bool isPowerOfTwo(int n) {
if (n <= 0) return false;
return (n & (n - 1)) == 0;
}
取余
//得到余數
int Yu(int num,int n)
{
int i = 1 << n;
return num&(i-1);
}
指定二進制位數截取
比如說16位二進制數A:1001 1001 1001 1000
,如果來你想獲A的哪一位的值,就把數字B:0000 0000 0000 0000
的那一位設置為1.
比如說我想獲得A的第三位就把B的第三位數字設置為1,則B為0000 0000 0000 0100
,設置完之后再把A、B求與, 其結果若為0,說明A的第三位為0,其結果為1,說明A的第三位為1.
同理:若要獲得A的第五位,就把B設置為0000 0000 0001 0000,
之后再求與。
通常在我們的程序中,數字B被稱為掩碼,其含義是專門用來測試某一位是否為0的數值。
統計二進制中 1 的個數
利用x=x&(x-1)
,會將x用二進制表示時最右邊的一個1變為0,因為x-1會將該位變為0.
int Count(int x)
{ int sum=0;
while(x)
{ sum++;
x=x&(x-1);
}
return sum;
}
生成組合編碼,進行狀態壓縮
當把二進制當作集合使用時,可以用or操作來增加元素。合并編碼 在對字節碼進行加密時,加密后的兩段bit需要重新合并成一個字節,這時就需要使用or操作。
求一個數的二進制表達中0的個數
int Grial(int x)
{
int count = 0;
while (x + 1)
{
count++;
x |= (x + 1);
}
return count;
}
兩個整數交換變量名
void swap(int &a, int &b) {
a ^= b;
b ^= a;
a ^= b;
}
判斷兩個數是否異號
int x = -1, y = 2;
bool f = ((x ^ y) < 0); // true
int x = 3, y = 2;
bool f = ((x ^ y) < 0); // false
數據加密
將需要加密的內容看做A,密鑰看做B,A ^ B=加密后的內容C。而解密時只需要將C ^ 密鑰B=原內容A。如果沒有密鑰,就不能解密!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define KEY 0x86
int main
{
char p_data[16] = {"Hello World!"};
char Encrypt[16]={0},Decode[16]={0};
int i;
for(i = 0; i < strlen(p_data); i++)
{
Encrypt[i] = p_data[i] ^ KEY;
}
for(i = 0; i < strlen(Encrypt); i++)
{
Decode[i] = Encrypt[i] ^ KEY;
}
printf("Initial date: %s\n",p_data);
printf("Encrypt date: %s\n",Encrypt);
printf("Decode date: %s\n",Decode);
return 0;
}
數字判重
利用了二進制數的性質:x^y^y = x
。我們可見,當同一個數累計進行兩次xor操作,相當于自行抵銷了,剩下的就是不重復的數
找出沒有重復的數
int find(int[] arr){
int tmp = arr[0];
for(int i = 1;i < arr.length; i++){
tmp = tmp ^ arr[i];
}
return tmp;
}
交換符號
int reversal(int a) {
return ~a + 1;
}
取絕對值(效率高)
n>>31 取得n的符號
若n為正數,n>>31等于0
若n為負數,n>>31等于-1
若n為正數 n^0=0,數不變
若n為負數,有n^-1 需要計算n和-1的補碼,然后進行異或運算,結果n變符號并且為n的絕對值減1,再減去-1就是絕對值
int abs(int n)
{
return (n ^ (n >> 31)) - (n >> 31);
}
也可以這樣使用
int abs(int n)
{
int i = n >> 31;
return i == 0 ? n : (~n + 1);
}
從低位到高位.將n的第m位置1
將1左移m-1位找到第m位,得到000...1...000
, n在和這個數做或運算
int setBitToOne(int n, int m)
{
return n | (1 << (m-1));
}
同理從低位到高位,將n的第m位置0,代碼如下
int setBitToZero(int n, int m)
{
return n & ~(1 << (m-1));
}
求2的N次方
1<<n
高低位交換
unsigned short a = 34520;
a = (a >> 8) | (a << 8);
進行二進制逆序
unsigned short a = 34520;
a = ((a & 0xAAAA) >> 1) | ((a & 0x5555) << 1);
a = ((a & 0xCCCC) >> 2) | ((a & 0x3333) << 2);
a = ((a & 0xF0F0) >> 4) | ((a & 0x0F0F) << 4);
a = ((a & 0xFF00) >> 8) | ((a & 0x00FF) << 8);
獲得int型最大最小值
int getMaxInt
{
return (1 << 31) - 1;//2147483647, 由于優先級關系,括號不可省略
}
int getMinInt
{
return 1 << 31;//-2147483648
}
m的n次方
//自己重寫的pow方法
int pow(int m , int n){
int sum = 1;
while(n != 0){
if(n & 1 == 1){
sum *= m;
}
m *= m;
n = n >> 1;
}
return sum;
}
找出不大于N的最大的2的冪指數
int findN(int n){
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8 // 整型一般是 32 位,上面我是假設 8 位。
return (n + 1) >> 1;
}
二分查找32位整數的前導0個數
int nlz(unsigned x)
{
int n;
if (x == 0) return(32);
n = 1;
if ((x >> 16) == 0) {n = n +16; x = x <<16;}
if ((x >> 24) == 0) {n = n + 8; x = x << 8;}
if ((x >> 28) == 0) {n = n + 4; x = x << 4;}
if ((x >> 30) == 0) {n = n + 2; x = x << 2;}
n = n - (x >> 31);
return n;
}
位圖的操作
將 x 的第 n 位置1,可以通過 x |= (x << n)
來實現
set_bit(char x, int n);
將 x 的第 n 位清0,可以通過 x &= ~(1 << n)
來實現
clr_bit(char x, int n);
取出 x 的第 n 位的值,可以通過 (x >> n) & 1
來實現
get_bit(char x, int n);
如下:
#define clr_bit(x, n) ( (x) &= ~(1 << (n)) )
#define set_bit(x, n) ( (x) |= (1 << (n)) )
#define get_bit(x, n) ( ((x)>>(n)) & 1 )
以下僅列出,感興趣可以參考下面鏈接.
關于操作計數方法
計算整數的符號
檢測兩個整數是否具有相反的符號
計算無分支的整數絕對值(abs)
計算兩個整數的最小值(最小值)或最大值(最大值),而無需分支
確定整數是否為2的冪
標志延伸
從恒定位寬擴展的符號
從可變位寬擴展的符號
通過3個操作從可變位寬擴展符號 有條件地設置或清除位而不分支
有條件地否定一個值而不分支
根據掩碼合并兩個值中的位
計數位設置
計數位設置,幼稚的方式
計算由查找表設置的位
數位集,Brian Kernighan的方式
使用64位指令對14、24或32位字中設置的位進行計數
并行設置計數位
從最高有效位到給定位置的計數位的設置(等級)
從給定的計數(等級)中選擇位位置(從最高有效位開始)
計算奇偶校驗(如果設置了奇數位數,則為1,否則為0)
天真地計算單詞的奇偶性
通過查找表計算奇偶校驗
使用64位乘法和模數除法計算字節的奇偶校驗
用乘法計算單詞的奇偶校驗
并行計算奇偶校驗
交換價值
用減法和加法交換值
用XOR交換值
用XOR交換單個位
反轉位序列
反轉位是顯而易見的方式
逐字查找表中的位反轉
通過3個操作(64位乘法和模數除法)反轉字節中的位
通過4個操作反轉字節中的位(64位乘法,無除法)
通過7個操作反轉字節中的位(無64位,僅32位)
與5 * lg(N)個運算并行地反轉N位數量
模數除法(又名計算余數)
在不進行除法運算的情況下,將模數除以1 << s(顯而易見)
在不進行除法運算的情況下以(1 << s)-1計算模數除法
不進行除法運算就并行計算(1 << s)-1的模數除法
查找整數的整數對數2(又稱最高位集的位置)
使用O(N)運算找到MSB N設置為整數的對數2(顯而易見的方法)
查找具有64位IEEE浮點數的整數的整數對數2
使用查找表找到整數的對數2
在O(lg(N))運算中找到N位整數的對數2
使用乘法和查找在O(lg(N))操作中找到N位整數的對數2
查找整數的對數以10為底的整數
查找整數的整數對數10
查找32位IEEE浮點數的整數對數基數2
查找32位IEEE浮點的pow(2,r)根的整數對數基數2(對于無符號整數r)
計算連續的尾隨零位(或查找位索引)
線性計算右邊的連續零位(后綴)
并行計算右側連續的零位(后綴)
通過二進制搜索計算右邊連續的零位(跟蹤)
通過強制轉換為浮點數來計算右側連續的零位(跟蹤)
用模數除法和查找計算右邊連續的零位(跟蹤)
用乘法和查找計數右邊連續的零位(后跟)
通過浮法舍入到2的下一個最高冪
向上舍入到2的下一個最高冪
交織位(也稱為計算莫頓數)
交錯位的明顯方式
通過表查找交織位
帶64位乘法的交織位
通過二進制幻數交錯位
測試單詞中的字節范圍(并計算出現的次數)
確定單詞是否為零字節
確定一個單詞的字節數是否等于n
確定一個單詞的字節數是否小于n
確定單詞的字節數是否大于n
確定單詞是否在m和n之間有一個字節
按詞典順序計算下一位排列
http://graphics.stanford.edu/~seander/bithacks.html
s中控制小數點的顯示位數
< script language = " JScript " >
Number.prototype.toFixed = function(num)
{
// 重新構造toFixed方法,IE5.0+
with(Math) this .NO = round( this .valueOf() * pow( 10 ,num)) / pow( 10 ,num);
return String( / /. / g.exec( this .NO) ? this .NO: this .NO + " . " + String(Math.pow( 10 ,num)).substr( 1,num));
}
alert(( 12.9299 ).toFixed( 2 ));
alert(( 12.9999 ).toFixed( 2 ));
</ script >
控制保留幾位有效小數的js函數
//Code CreateBy abandonship 2007.03.12
function FormatAfterDotNumber( ValueString, nAfterDotNum )
{
var ValueString,nAfterDotNum ;
var resultStr,nTen;
ValueString = ""+ValueString+"";
strLen = ValueString.length;
dotPos = ValueString.indexOf(".",0);
if (dotPos == -1)
{
resultStr = ValueString+".";
for (i=0;i<nAfterDotNum ;i++)
{
resultStr = resultStr+"0";
}
return resultStr;
}
else
{
if ((strLen - dotPos - 1) >= nAfterDotNum ){
nAfter = dotPos + nAfterDotNum + 1;
nTen =1;
for(j=0;j<nAfterDotNum ;j++){
nTen = nTen*10;
}
resultStr = Math.round(parseFloat(ValueString)*nTen)/nTen;
return resultStr;
}
else{
resultStr = ValueString;
for (i=0;i<(nAfterDotNum - strLen + dotPos + 1);i++){
resultStr = resultStr+"0";
}
return resultStr;
}
}
}
應用時只需要FormatAfterDotNumber( ’數字字符串’, 保留小數位數 );
for example:
<html>
<head>
<SCRIPT LANGUAGE="JAVAscript">
<!--調用上面的函數 -->
</script>
</head>
<body>
<input type="text" name="strTemp">
<input type="button" onclick="alert( FormatAfterDotNumber( document.all. strTemp.value), 保留小數位)" >
</body>
</html>
一個替代js自帶的toFixed函數的方法和優點
之前一直在用這個js自帶的toFixed函數來進行四舍五入的操作,可是,在實際使用過程中卻遇到了問題。
比如
Javascript代碼
var money=0.00542;//0.006;
alert(Number(money).toFixed(2));
//0.00
可以看出上面的結果是錯誤的,下面的方法通過巧妙的使用Math.round函數,完全可以解決數值很小時的精度問題。
Javascript代碼
var money=0.00542;//0.006;
alert(Number(money).toFixed(2));
function round2(number,fractionDigits){
with(Math){
return round(number*pow(10,fractionDigits))/pow(10,fractionDigits);
}
}
alert(round2(money,2));//0.01
round 方法
返回與給出的數值表達式最接近的整數。
Math.round(number)
必選項 number 參數是要舍入到最接近整數的值。
說明
如果 number 的小數部分大于等于 0.5,返回值是大于 number 的最小整數。否則,round 返回小于等于 number 的最大整數。
js保留小數位數的某人總結
一、問題的產生:
自己在編碼時,在javascript中遇到了3.21*3=9.629999999999999的現象
二、百度一下
得到如下信息:
用Javascript取float型小數點后兩位,例22.127456取成22.13,如何做?
1. 最笨的辦法....... [我就怎么干的.........]
function get()
{
var s = 22.127456 + "";
var str = s.substring(0,s.indexOf(".") + 3);
alert(str);
}
2. 正則表達式效果不錯
<script type="text/javascript">
onload = function(){
var a = "23.456322";
var aNew;
var re = /([0-9]+/.[0-9]{2})[0-9]*/;
aNew = a.replace(re,"");
alert(aNew);
}
</script>
3. 他就比較聰明了.....
<script>
var num=22.127456;
alert( Math.round(num*100)/100);
</script>
4.會用新鮮東西的朋友....... 但是需要 IE5.5+才支持。
<script>
var num=22.127456;
alert( num.toFixed(2));
</script>
三、總結后,自己寫了個javascript多位數四舍五入的通用方法
//num表示要四舍五入的數,v表示要保留的小數位數。
function decimal(num,v)
{
var vv = Math.pow(10,v);
return Math.round(num*vv)/vv;
}
Math對象
屬性
LN10 (10的自然對數)
PI (3.1415926...)
SQRT1_2 (1/2的平方根)
方法
abs(x) 返回x的絕對值
acos(x) 返回x的arc cosine值
asin(x) 返回x的arc sin值
atan(x) 返回x的arc tangent值
ceil(x) 返回大于等于x的最小整數
cos(x) 返回x的cosine值
exp(x) 返回e的x次方
floor(x) 返回小于等于x的最大整數
log(x) 返回x的
max(x,y) 返回x,y中的大值
min(x,y) 返回x,y中的小值
pow(x,y) 返回x的y次方
round(x) 舍入到最近整數,(小于或等于0.5小數舍去)
sin(x) 返回x的sin值
sqrt(x) 返回x的平方根
tan(x) 返回x的tangent值
js浮點數相加、減、乘、除精確計算
說明:javascript的加法結果會有誤差,在兩個浮點數相加的時候會比較明顯。這個函數返回較為精確的加法結果。
//調用:accAdd(arg1,arg2)
//返回值:arg1加上arg2的精確結果
function accAdd(arg1,arg2){
var r1,r2,m;
try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}
try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}
m=Math.pow(10,Math.max(r1,r2))
return (arg1*m+arg2*m)/m
}
//說明:javascript的減法結果會有誤差,在兩個浮點數相加的時候會比較明顯。這個函數返回較為精確的減法結果。
//調用:accSub(arg1,arg2)
//返回值:arg1減上arg2的精確結果
function accSub(arg1,arg2){
return accAdd(arg1,-arg2);
}
//說明:javascript的乘法結果會有誤差,在兩個浮點數相乘的時候會比較明顯。這個函數返回較為精確的乘法結果。
//調用:accMul(arg1,arg2)
//返回值:arg1乘以arg2的精確結果
function accMul(arg1,arg2)
{
var m=0,s1=arg1.toString(),s2=arg2.toString();
try{m+=s1.split(".")[1].length}catch(e){}
try{m+=s2.split(".")[1].length}catch(e){}
return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)
}
//說明:javascript的除法結果會有誤差,在兩個浮點數相除的時候會比較明顯。這個函數返回較為精確的除法結果。
//調用:accDiv(arg1,arg2)
//返回值:arg1除以arg2的精確結果
function accDiv(arg1,arg2){
var t1=0,t2=0,r1,r2;
try{t1=arg1.toString().split(".")[1].length}catch(e){}
try{t2=arg2.toString().split(".")[1].length}catch(e){}
with(Math){
r1=Number(arg1.toString().replace(".",""))
r2=Number(arg2.toString().replace(".",""))
return (r1/r2)*pow(10,t2-t1);
}
}
歡迎關注公眾號(hongji8410)和加入QQ群一起交流(522342554)
系列教程是scikit-learn學習的第一篇,我會根據scikit-learn官網教程和自己的學習經驗來進行總結。首先,我會介紹模型的一些基本知識,不會花時間去推導公式,會介紹一下這個模型的適應情況,以及用scikit-learn這個框架來實現這個模型。
還記得高中物理實驗課的時候,做實驗的時候我們會首先記錄一系列的數據,然后根據這些自變量和因變量之間的關系(線性關系)畫出直線,而在畫直線的時候所采用的方法就是最小二乘法。最小二乘法也叫最小平方法是一種數學的優化算法,它是通過最小化誤差的平方和尋找數據的最佳函數匹配。利用最小二乘法可以簡便地求得未知的數據,并使得求得的數據與實際數據之間誤差的平方和最小。如果,自變量(x)和因變量(y)是線性組合的話,那么它們一定滿足下面的公式
線性模型
其中,w表示系數,可以用一個向量表示為W=(W1,W2......,Wp),在scikit-learn中,用coef_表示。其中W0表示截距,在scikit-learn中用intercept_表示。數據集的實際觀測數據和預測數據(估計值)之間的殘差平方和最小,公式如下:
殘差平方和
其中,Xw表示預測值,y表示實際數據。下面,引用一個維基百科的例子來介紹一下使用最小二乘法的求解過程
最小二乘法例子
通過上面的例子我們可以發現,我們是通過求解最小化誤差來求解參數的。然而,我們在實際編程的時候并不會采用這種方式去求解參數,通常都是采用梯度下降算法迭代來使得預測值與實際值之間誤差的平方和最小。在使用最小二乘法求解參數的時候有幾個地方需要注意:
1、方程組的個數要多于未知數的個數。
2、模型與參數是線性的,參數只能以一次方出現。
3、對數據的噪聲干擾之間是零均值同方差的,就是指在測量數據的時候要保證測量誤差的平均值為0,而且每一個測量誤差之間是不相關的,測量誤差與X是不相關的。
1、求解維基百科例子中的參數
from sklearn import linear_model import matplotlib.pyplot as plt import numpy as np if __name__ == "__main__": #定義自變量x x = np.array([[1],[2],[3],[4]],dtype=np.float32) #定義因變量y y = np.array([6,5,7,10],dtype=np.float32) #加載scikit-learn的線性模型 linear = linear_model.LinearRegression() #通過x和y來建立線性模型 linear.fit(x,y) #查看模型系數β2 print(linear.coef_) #[ 1.39999998] #查看模型的截距β1 print(linear.intercept_) #3.5000000596
2、scikit-learn官網的例子
http://sklearn.lzjqsdd.com/auto_examples/linear_model/plot_ols.html#example-linear-model-plot-ols-py
score(X, y, sample_weight=None)返回預測的決定系數R^2
R^2 = 1 - u/v,u是一個殘差的和squares ((y_true - y_pred) ** 2).sum() ,v是一個平方和squares ((y_true - y_true.mean()) ** 2).sum(),最好的結果是1,它也能為負數,因為這個模型有可能被任意的損壞,一個常量的模型總是能預測一個期望值,在不考慮特征輸入的情況,R^2=0。可以通過R^2來判斷,預測的值與實際值的均值之間的關系。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。