为了测试一下js和Canvas的计算能力,做了一个Mandelbrot的分形图,支持鼠标Zoom In。Mandelbrot的定义很简单,虚数平面的每个点(x,y),通过反复计算zn+1 = zn2 + c,z0 = 0。只有结果收敛才属于Mandelbrot,否则根据n的设定一个颜色,越大越深,代表接近属于集合的点,可以把集合中的点理解为n=无穷大。推荐在chrome中打开本页,还支持firefox和ie9。 拖动鼠标可以明显发现chrome是最流畅的。

更为专业的Mandelbrot请check这里 http://www.atopon.org/mandel/

Your browser does not support the canvas element.


<canvas id="canvas" width="600" height="480" style="margin-left:100px">
<p>Your browser does not support the canvas element.</p>
</canvas>
<p><input id="reset" type="button" value="Reset" /></p>

<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var width = canvas.width ,height = canvas.height;
var maxIterations = 100;
var minRe = -2.0;
var maxRe = 1.0;
var minIm = -1;
var maxIm = minIm+(maxRe-minRe)*height/width;

reset();

document.getElementById(
"reset").onclick = reset;

canvas.onmousedown
= function (evt) {
var x0 = evt.pageX - canvas.offsetLeft;
var y0 = evt.pageY - canvas.offsetTop;

var x1, y1, w, h;
var imgd = context.getImageData(0, 0, width, height);

update(evt);

function update(evt) {
x1
= evt.pageX - canvas.offsetLeft;
y1
= evt.pageY - canvas.offsetTop;
w
= Math.abs(x1 - x0), h = Math.abs(y1 - y0);
}

function clear(evt) {
if (w && h) {
context.clearRect(
0, 0, width, height);
context.putImageData(imgd,
0, 0);
}
}

canvas.onmousemove
= function (evt) {
clear(evt);
update(evt);
context.strokeStyle
= "red";
context.strokeRect(x0
< x1 ? x0 : x1, y0 < y1 ? y0 : y1, w, h);
}

canvas.onmouseup
= function (evt) {
clear(evt);
canvas.onmousemove
= canvas.onmouseup = null;

minRe
= minRe + (maxRe - minRe) / width * (x0 < x1 ? x0 : x1);
maxRe
= minRe + (maxRe - minRe) / width * w;
minIm
= minIm + (maxIm - minIm) / height * (y0 < y1 ? y0 : y1);
maxIm
= minIm + (maxIm - minIm) / height * h;

draw();
}
}

function reset() {
minRe
= -2.0;
maxRe
= 1.0;
minIm
= -1;
maxIm
= minIm + (maxRe - minRe) * height / width;
draw();
}

function draw() {
context.fillRect(
0, 0, width, height);
var imgd = context.getImageData(0, 0, width, height)
var pix = imgd.data;

var drawPixel = function (x, y, itr) {
var i = (y * width + x) * 4;

pix[i]
= pix[i + 1] = pix[i + 2] = Math.round(itr * 255 / maxIterations);
}

mandelbrot(width, height, drawPixel);
context.putImageData(imgd,
0, 0);
}

function mandelbrot(imageWidth, imageHeight, drawPixel) {
var re_factor = (maxRe-minRe)/(imageWidth-1);
var im_factor = (maxIm-minIm)/(imageHeight-1);

for(var y=0; y<imageHeight; ++y)
{
var c_im = maxIm - y*im_factor;
for(var x=0; x<imageWidth; ++x)
{
var c_re = minRe + x*re_factor;

var z_re = c_re, z_im = c_im;
var isInside = true;
var n = 0;
for(; n<maxIterations; ++n)
{
var z_re2 = z_re*z_re, z_im2 = z_im*z_im;
if(z_re2 + z_im2 > 4)
{
isInside
= false;
break;
}
z_im
= 2*z_re*z_im + c_im;
z_re
= z_re2 - z_im2 + c_re;
}

if (!isInside) { drawPixel(x, y, n); }
}
}
}
</script>
posted @ 2011-05-26 22:46 dragonpig 阅读(178) 评论(0) 编辑
class Student
{
public string Name { get; set; }
}

static double Test(int loop, Student stu, Func<Student, string> action)
{
var watch
= Stopwatch.StartNew();
string s = null;
for (var i = 0; i < loop; i++)
s
= action(stu);

return watch.ElapsedTicks;
}

static Func<Student, string> NativeGetter()
{
return s => s.Name;
}

static Func<Student, string> ReflectedGetter()
{
var type
= typeof (Student);
var prop
= type.GetProperty("Name");

return s => (string)prop.GetValue(s, null);
}

static Func<Student, string> EmittedGetter()
{
var dm
= new DynamicMethod(name: "EmittedGetter", returnType: typeof(string), parameterTypes: new[] { typeof(Student) }, owner: typeof(Student));

var type
= typeof (Student);
var prop
= type.GetMethod("get_Name");
var il
= dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, prop);
il.Emit(OpCodes.Ret);

return (Func<Student, string>)dm.CreateDelegate(typeof(Func<Student, string>));
}

static Func<Student, string> ExpressionGetter()
{
var type
= typeof(Student);
var prop
= type.GetMethod("get_Name");

ParameterExpression pa
= Expression.Parameter(typeof(Student));
Expression body
= Expression.Call(pa, prop);

return Expression.Lambda<Func<Student, string>>(body, pa).Compile();
}

static Func<Student, string> DynamicGetter()
{
return s => { dynamic d = s; return d.Name; };
}

[MethodImpl(MethodImplOptions.NoOptimization)]
public static void Run()
{
const int loop = 5000000;

var stu
= new Student {Name = "Mike"};

var dynamic
=
Test(loop, stu, DynamicGetter());

var expression
=
Test(loop, stu, ExpressionGetter());

var native
=
Test(loop, stu, NativeGetter());

var emitted
=
Test(loop, stu, EmittedGetter());

var reflected
=
Test(loop, stu, ReflectedGetter());

Console.WriteLine(
"native:{0}\ndynamic:{1}\nemit:{2}\nexpression:{3}\nreflection:{4}", 1, dynamic / native, emitted / native, expression / native, reflected / native);

Console.ReadKey();
}

测试结果

1. 当循环次数比较小的时候, loop=1000

native:1
dynamic:540.444964871194
emit:0.704918032786885
expression:0.224824355971897
reflection:8.37002341920375

2. loop=5000000

native:1
dynamic:4.37328053807767
emit:0.96159470600998
expression:1.00412887828162
reflection:35.909097418095

posted @ 2011-05-01 00:18 dragonpig 阅读(590) 评论(2) 编辑

当跨assemblies的时候要特别注意两者的区别, 请看这篇文章

if the scope of your constant is limited to just one assembly, class, or smaller (you can define a const inside a method), this is not a big deal.  However, if the const is visible outside the assembly it is defined in, we must be wary!  Because the const’s value is substituted at compile time, this means that if the assembly that defines the const changes its value, but the calling assembly isn’t recompiled, then the calling assembly will still see the original value.

Let’s illustrate.  Assume a class library called Shapes.DLL that defines this:

   1: public class Circle
   2: {
   3:     public const double Pi = 3.14;
   4:     
   5:     // ...
   6: }

Now let’s assume a separate program called Drawing.EXE adds a reference to Shapes.DLL and uses the const:

   1: public static class Drawing
   2: {
   3:     public static void Main()
   4:     {
   5:         Console.WriteLine(“Pi is: “ + Circle.Pi);
   6:     }
   7: }

If we run this, we get:

   1: Pi is 3.14

Now let’s say during the QA process someone decides that this value of Pi is not precise enough and changes the definition:

   1: public const double Pi = 3.1415927;

And they rebuild the Shapes.DLL and just drop it into the deployment directory for Drawing.EXE without rebuilding it.  What happens if we run Drawing.EXE again without recompiling?  We get:

   1: Pi is 3.14

Whoa!  Even though we changed the value of Pi in our referenced assembly and deployed it to where Drawing.EXE expected it and Drawing.EXE loaded it, it still prints 3.14.  This is because const is a compile-time substitution.  Thus, if you change the value of a const, it will not be picked up until the code using it is recompiled as well.  If we recompile and run Drawing.EXE, we will get:

   1: Pi is 3.1415927

Thus, const should be used mainly for values that are not subject to change, or freely if the scope of the const is limited to the same assembly or smaller.

posted @ 2011-03-25 16:48 dragonpig 阅读(258) 评论(0) 编辑

在sqlserver中可以这样显示分组前N个成员, 关键在row_number, partition

select * from
(select schoolmember_id, row_number() over(partition by school_id order by schoolmember_id ) as number from schoolmember) as a
where a.number < 3

posted @ 2011-03-22 18:04 dragonpig 阅读(110) 评论(0) 编辑
private static int BinarySearch(T[] array, int index, int length, T value)
{
int lo = index;
int hi = index + length - 1;
while (lo <= hi)
{
int i = lo + ((hi - lo) >> 1);
int order;
if (array[i] == null)
{
order
= (value == null) ? 0 : -1;
}
else
{
order
= array[i].CompareTo(value);
}

if (order == 0)
{
return i;
}

if (order < 0)
{
lo
= i + 1;
}
else
{
hi
= i - 1;
}
}

return ~lo;
}

最后一手~lo精妙。如果找不到value。当hi = lo + 1时。

1.如果value > lo。必然发生lo = lo + 1。~~lo落在插入点。

2.如果value < lo。必然发生lo。~~lo依然落在插入点上。

证毕

posted @ 2011-03-08 16:19 dragonpig 阅读(80) 评论(0) 编辑
摘要: declare @text nvarchar(500) ,@delimiter nchar(1)set @text = '1,2,3'set @delimiter = ',' set @text = @text + @delimiter;WITH CSV([index], [comma_index])as(select [index] = 1, [comma_index] = CHARINDEX(@delimiter, @text) union allselect [index] = [comma_index] + 1, [comma_index] = CHAR阅读全文
posted @ 2011-03-02 17:24 dragonpig 阅读(65) 评论(0) 编辑
摘要: 通过SqlServer的Common Table Expressions (CTE)可以进行递归计算。参见Using Common Table Expressions 和 Recursive Queries Using Common Table Expressions通过CTE计算FibonacciWITH Fib(a, b)AS(SELECT 0,1 UNION allSELECT b, a+b FROM Fib WHERE b < 10)SELECT * FROM Fib阅读全文
posted @ 2011-03-02 16:48 dragonpig 阅读(69) 评论(0) 编辑
摘要: 由于最近较忙,上一篇的坑估计要慢慢填了。感觉写文章介绍要比写程序还累啊。先看看测试程序,能够了解api支持哪些功能:static void Main(string[] args){ //wrapper对象 dynamic data = DJson.Wrap(new { name = "Jane", male = false, age = 24, dob = DateTime.Now, friend = new { name = "Jesse", male = true, age = 32, dob = DateTime.Now }, mobile = n阅读全文
posted @ 2011-02-27 18:39 dragonpig 阅读(172) 评论(0) 编辑
摘要: 参考 http://www.yoda.arachsys.com/csharp/singleton.html双lock的singleton性能非常差,这里推荐inner class的方式,并且加上泛型。public class Singleton<T> where T : new(){ public static T Instance { get { return Nested.instance; } } private class Nested { //suppress optimization in .net v1.1 static Nested() { } internal s阅读全文
posted @ 2011-02-27 18:25 dragonpig 阅读(198) 评论(0) 编辑
摘要: 通过jQuery.get是不能异步访问跨域资源的。主要是因为安全考虑,否则其他域有可能获得当前页的cookie造成隐私泄漏。但js确可以跨域访问,因为所有浏览器都支持refer外部的js文件。访问外部域的js时会发送外部域的cookie,这样在返回的js中就能获取值了。创建两个website,分别叫local.domain1.com和local.domain2.comdomain1中负责set和get本域的cookie,分别为setcookie.aspx和getcookie.aspx//setcookie.aspxpublic partial class SetCookie : System.阅读全文
posted @ 2011-02-27 18:04 dragonpig 阅读(1433) 评论(0) 编辑