| mr_oydy@hotmail...'s profilehpho的共享空间PhotosBlogLists | Help |
hpho的共享空间 |
||||
多维存取适配器因为使用了偏特化,所以需要VS2005以上编绎器编绎.
其原理很简单: 有n维T类型数组T arr1[D_n][D_n-1]...[D_1]和1维数组arr2[D_n*D_n-1*...*D_1]; 所以sizeof(arr1)==sizeof(arr2);假设arr1和arr2内容相同. 设 d_1 = D_n-1 * ... * D_1; ... d_n-1 = D_1; 则有多项式 f(a_1,...,a_n-1,a_n) = (a_1*d1) + ... + (a_n-1*d_n-1) + a_n; arr1[a_1]...[a_n] = arr2[f(a_1,...,a_n-1,a_n)]; #include<iostream>
template<typename T, int sz>
class DimAdapter { public: typedef T TYPE; DimAdapter(TYPE* p):ptr(p){pp = 0;} private: TYPE* ptr; int pp; public: T& operator[](int i)
{ return ptr[i + pp]; } DimAdapter& pos(int i){pp = i;return *this;} int dim(){return sz;} }; template<typename T,int sz,int zz> class DimAdapter<DimAdapter<T,sz>, zz> { private: DimAdapter<T,sz> low; int pp; public: typedef typename DimAdapter<T,sz>::TYPE TYPE; DimAdapter(TYPE* p):low(p){pp = 0;} DimAdapter<T,sz>& operator[](int i) { return low.pos(pp + low.dim() * i); } DimAdapter& pos(int i){pp = i;return *this;} int dim(){return zz * low.dim();} }; #define ADAPTER_DIM2(t,d1,d2) \
DimAdapter<DimAdapter<t,d2>,d1> #define ADAPTER_DIM3(t,d1,d2,d3) \ DimAdapter<ADAPTER_DIM2(t,d2,d3),d1> #define ADAPTER_DIM4(t,d1,d2,d3,d4) \ DimAdapter<ADAPTER_DIM3(t,d2,d3,d4),d1> #define ADAPTER_DIM5(t,d1,d2,d3,d4,d5) \ DimAdapter<ADAPTER_DIM4(t,d2,d3,d4,d5),d1> #define ADAPTER_DIM6(t,d1,d2,d3,d4,d5,d6) \ DimAdapter<ADAPTER_DIM5(t,d2,d3,d4,d5,d6),d1> #define ADAPTER_DIM7(t,d1,d2,d3,d4,d5,d6,d7) \ DimAdapter<ADAPTER_DIM6(t,d2,d3,d4,d5,d6,d7),d1> /////////////////////////////////////////////
int main() { using namespace std; int array[2*3*5]; for(int i = 0;i<30;++i) array[i] = i; ADAPTER_DIM2(int,2,15) ad1 = array; ADAPTER_DIM2(int,6,5) ad2 = array; ADAPTER_DIM3(int,3,2,5) ad3 = array; for(int i = 0;i<2;++i) for(int j = 0;j<15;++j) cout << ad1[i][j] << " "; cout << endl; for(int i = 0;i<6;++i) for(int j = 0;j<5;++j) cout << ad2[i][j] << " "; cout << endl; for(int i = 0;i<3;++i) for(int j = 0;j<2;++j) for(int k = 0;k<5;++k) cout << ad3[i][j][k] << " "; return 0; } rational number 与 irrational number 顺便一提,rational number 跟 irrational number 为什么被译成"有理数"与"无理数"的事情.
大家都会觉得很迷惑吧!原来日本大约十七,十八世纪接触西方数学的时候,他们就这么作了翻译, 后来中国人参照日本的译名依样采用,因而造成大错.其实rational这个字的字根是ratio,它是名词, 也就是比例的意思.如何把这个名词的字变化成形容词呢?一般的作法是直接在名词字尾加上"al", 但由于它最后一个字母"o"是母音,不能直接加"al"(因为a也是母音),需要先加一个字音之后再加"al", 于是就变成加上"n"之后再加上"al",而演变成ratio-n-al.其实rational这个字(在这里)跟"有理"一点都扯不上关系呢! 当初的人搞错了,后来的人跟著错下去,真是"一失足成千古恨"呀.... 摘自 数学传播32卷1期
<再说sqrt(2)为无理数> my_atan反正切之前用泰勒展开式来写atan,结果收敛非常慢,现在用牛迭速度快很多了.
具体简单的复习一下牛迭:
解非线性方程f(x)=0的牛顿法是把非线性方程线性化的一种近似方法。
把f(x)在x0点附近展开成泰勒级数 f(x) = f(x0)+(x-x0)f'(x0)+(x-x0)^2*f''(x0)/2! +… 取其线性部分,
作为非线性方程f(x) = 0的近似方程,即泰勒展开的前两项,
则有f(x0)+f'(x0)(x-x0)=f(x)=0 设f'(x0)≠0则其解为x1=x0-f(x0)/f'(x0) 这样,
得到牛顿法的一个迭代序列:x(n+1)=x(n)-f(x(n))/f'(x(n))。
代码:
#include <stdio.h>
#include <math.h> double my_atan(double a){
/*
// fx = tanx - a // f'x = 1/(cosx)^2 // fx = fa + f'a*(x-a) // [xn+1] = f[xn] + f'[xn]([xn]-a) // [xn+1] = [xn] - cos[xn]*sin[xn] + (a*cos[xn]^2)
*/
double x = 0; while(fabs(sin(x)/cos(x)-a)>=1e-7) x -= (cos(x)*sin(x) - a*cos(x)*cos(x)); return x; } void main(int argc, char *argv[]) { double RA = -3.1415/2; double i = RA; for(;i<-RA;i+=0.1) printf("%7f %7f\n", atan(i), my_atan(i)); } my_pow幂函数/*
牛顿二项式: f(x) = (1+x)^a ; 仅当|x|<1, a<1才有效
其泰勒展式: f(x) = f(a) + f'(a)(x-a) + (f''(a)(x-a)^2)/2! + ...
*/ double my_pow(double _x, double a){ double r = 1.0f,x,A,X,L; long l = 1; /* 处理如my_pow(4,0.5)情况. 1/my_pow(1/4,0.5);
if(a<1. && _x>1.) x = 1./_x; */ x = x - 1.0; A = a; X = x; L = l; /* 误差: 1/10! = 2.7557319223985890652557319223986e-7 */
while(l<=10){
r+=(A*X)/L; A*=(a-l); X*=x; L*=++l; } /* return (a<1. && _x>1.)?1./r:r; */ return r; } 精度和强度都比math.h的pow弱, 仅作为基于数分的实践. using Lagrange Interpolation Polynomial replace 'switch'#define BASEFUN(x,a,b,c,d) (((x-b)*(x-c)*(x-d))/((a-b)*(a-c)*(a-d))) #define CALC(op, l, r) BASEFUN(op,'+','-','*','/')*(l+r)+ \
BASEFUN(op,'-','+','*','/')*(l-r)+ \ BASEFUN(op,'*','+','-','/')*(l*r)+ \ BASEFUN(op,'/','+','-','*')*(l/r) int main(int argc,char *argv[]) { char op; float lv,rv; scanf("%f%c%f",&lv,&op,&rv); printf("%.3f%c%.3f=%.3f\n",lv,op,rv,CALC(op,lv,rv)); return 0; } Permutation Algorithmvoid permutable(char* str, int len, char* out, int j){ // 打印所有元素的全排列
int i; char tmp; if(len>=1){
for(i=0; i<len; ++i){ tmp=*str;*str=str[i];str[i]=tmp; out[j]=*str; permutable(str+1, len-1,out,j+1); tmp=*str;*str=str[i];str[i]=tmp; } if(len==1){ out[j+1]=0; printf("%s\n",out); } } } ------------------------------------------------------------------------------------
算法正确性证明:
用归纳法,
设:S是不为空的集合, 表示为S = {e_1,e_2,...,e_n}; {n|1,2,3,...};
1,当有2个元素时,交换(e_1,e_2)便得到另一个排列(e_2,e_1),即2!=2.
2,设当N个元素时成立.
3,则若有N+1个元素时,在N+1中取e_1,
做交换(e_1,e_x) ;{x|2...n+1}, 便有新的一个拥有N个元素的子集(e_1,e_3,...,e_n+1),
这时会有N个不同的这样的子集且再加上原来(e_2,e_3...,e_n+1),共有N+1个大小为N个元素的子集.
然后因为元素为N个时此作法成立(即(N+1)*N*...*1=n!), 因此算法得证#
因为N个元素时成立,所以算法得证#
用stl的函数推砌trim()函数#include <algorithm>
#include <functional>
#include <string>
namespace hpho{
template<typename Bgn, typename End, typename T>
Bgn trim(Bgn bgn, End end, T v){ using namespace std; typedef reverse_iterator<char*,char> RIter;
End nend; copy(nend=find_if(bgn,end,bind1st(not_equal_to<char>(),v)), end, bgn); // 去前空格 RIter rbgn(bgn+(end-nend)-1), // 利用反转迭代器
rend=reverse_iterator<char*,char>(bgn); find_if(rbgn,rend,bind1st(not_equal_to<char>(),v))[-1]='\0'; // 去后空格 return bgn; } }
int main(void)
{ using namespace hpho;
std::string s=" abc sss "; trim(s.begin(),s.end(),' '); printf("[%s]",s.c_str()); return 0;
} 初等行变换求逆矩阵这是用初等行变换做的矩阵求逆
// 某行乘一个数
void f(double* v, int n, double d){
int j; for(j=0;j<n;++j){ v[j]*=d; } } // 某行乘一个数后加的另一行
void g(double* v1, double* v2, int n, double d){
int j; double t; for(j=0;j<n;++j){ t=v1[j]*d; v2[j]+=t; } } // 利用f()和g()两个变换求逆矩
void inverseM(double* m1, double* m2,int n){
int i,j; double d; for(i=0;i<n;++i){ d=1.0/m1[n*i+i]; f(m1+n*i,n,d);f(m2+n*i,n,d); for(j=0;j<n;++j){ if(i!=j){
d=-m1[n*j+i]; g(m1+n*i,m1+n*j,n,d);g(m2+n*i,m2+n*j,n,d); } } } } void printM(double* m, int n){ int i,j; for(i=0;i<n;++i){ for(j=0;j<n;++j){ printf("%f ", m[n*i+j]); } printf("\n"); } } int main(){
double m[9]={5.3,4.2,8.5,9.4,6.8,5.8,3.7,7.6,1.8};
double m1[9]={1,0,0,0,1,0,0,0,1};
inverseM(m,m1,3);
printM(m1,3);
}
把有中文英文混合的串分解为固定长度的子串#include <ctype.h>
int truncation(char const* src, int slen, int idx, char* line, int len){
int j=idx+len, k=0; while(idx<slen&&idx<j) { *line=src[idx]; if(isprint((unsigned char)*line)) ++k; ++idx; ++line; } if(idx>=slen) { *line='\0'; return idx; } else if((len-k)>0&&(len-k)%2) { *(line-1)='\0';--idx; } *line='\0'; return idx; } int main(){
char text[]="一切从实际出发1,二氧化碳, abc三番五次123def"; char buf[7]; int i=0,l=strlen(text); while(i<l) { i=truncation(text,l,i,buf,sizeof(buf)-1); printf("%s\n",buf); } return 0;
}
/////////////////////////////////////////////////
1,必须注意char是有符号的.
2,使用isXXX函数时务必加强转型为unsigned char,理由是1.
3,若函数是需要加工串(如:统计,截断,...)时一般最好还是使用内建的类型指针.
上述函数参数若用string或CString的话就必须先复制再统计,或时一边统计一边调用operator[]()或at()还处理每一个字符.这样增加了处理成本! 题目一、题目:
这个题目比较变态 [所有相关帖子] 只用以下的符号: ~, !, ^,&, +, |, <<, >>. 实现 x?y:z
二、偶的答案:
y & ~x + x + !x | z & ~x + x + !!x; 三、分析:
整个式子由三部分构成:
1, ~x + x 2, !x 和 !!x 3, y & (1 + 2) 1,
无论x是什么数 ~x + x 等同 ~x | x 等同 0xffffffff 2,
!x和!!x结果只会是0或1, 因为!操作符返回的是一个bool(true, false) 3, 1+2的意思
(~x + x + !x)和(~x + x + !!x) 意思就是: 0xffffffff + 0 或 0xffffffff + 1 而0xffffffff + 1等于0 4, 最终是要x!=0时产生0和0xffffffff, x==0时产生0xffffffff和0
这就做到(y & 0 | z & 0xffffffff) 或 (y & 0xffffffff | z & 0) 的效果. (y&0) 和 (z&0) 结是0
(y & 0xffffffff)和(z & 0xffffffff)都会自己y和z. 因为题目没给用"()"的原因所以要特别注意运算符级别因此没选用(~x | x)而是用(~x + x). 看完这个后或许大家会有更好的答案, 期待中......! :-)
注: 这里假定x,y,z为整形
posted on 2005-12-13 15:06 metaprogram的BLOG |
|
|||
|
|