<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>.NET | 酷 壳 - CoolShell</title>
	<atom:link href="https://coolshell.cn/tag/net/feed" rel="self" type="application/rss+xml" />
	<link>https://coolshell.cn</link>
	<description>享受编程和技术所带来的快乐 - Coding Your Ambition</description>
	<lastBuildDate>Mon, 17 Mar 2014 00:56:54 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2</generator>
	<item>
		<title>一个浮点数跨平台产生的问题</title>
		<link>https://coolshell.cn/articles/11235.html</link>
					<comments>https://coolshell.cn/articles/11235.html#comments</comments>
		
		<dc:creator><![CDATA[tanglei.name]]></dc:creator>
		<pubDate>Sat, 15 Mar 2014 12:44:24 +0000</pubDate>
				<category><![CDATA[.NET编程]]></category>
		<category><![CDATA[C/C++语言]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[float]]></category>
		<category><![CDATA[FPU]]></category>
		<category><![CDATA[SSE]]></category>
		<guid isPermaLink="false">http://coolshell.cn/?p=11235</guid>

					<description><![CDATA[<p>感谢网友唐磊（微博@唐磊_name）投稿，本文原文在唐磊的博客上（原文地址），原文分析还不够好，而且可能对人有误导，所以，我对原文做了很多修改，并加了Linux...</p>
<p class="read-more"><a class="btn btn-default" href="https://coolshell.cn/articles/11235.html"> Read More<span class="screen-reader-text">  Read More</span></a></p>
The post <a href="https://coolshell.cn/articles/11235.html">一个浮点数跨平台产生的问题</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></description>
										<content:encoded><![CDATA[<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415450859608158"
     crossorigin="anonymous"></script><strong>感谢网友<a href="http://www.tanglei.name/" target="_blank">唐磊</a>（微博@<a title="唐磊_name" href="http://weibo.com/tangleithu?from=feed&amp;loc=nickname">唐磊_name</a>）投稿，本文原文在唐磊的博客上（<a href="http://www.tanglei.name/a-bug-relate-with-float-point-between-x86-and-x64-in-csharp/">原文地址</a>），原文分析还不够好，而且可能对人有误导，所以，我对原文做了很多修改，并加了Linux下的内容。浮点数是一个很复杂的事情，希望这篇文章有助于大家了解浮点数与其相关的C/C++的编译选项。</strong>（注：我没有Windows 32位以及C#的环境，所以，对于Windows 32位的程序和C#的程序没有验证过）</p>
<p>背景就简单点儿说，最近一个项目C#编写，涉及浮点运算，来龙去脉省去，直接看如下代码。</p>
<pre data-enlighter-language="csharp" class="EnlighterJSRAW">float p3x = 80838.0f;
float p2y = -2499.0f;
double v321 = p3x * p2y;
Console.WriteLine(v321);</pre>
<p>很简单吧，马上笔算下结果为-202014162，没问题，难道C#没有产生这样的结果？不可能吧，开启Visual Studio，copy代码试试，果然结果是-202014162。就这样完了么？显然没有！你把编译时的选项从AnyCPU改成x64试试~(服务器环境正是64位滴哦！！)结果居然边成了-202014160，对没错，就是-202014160。有点不相信，再跑两遍，仍然是-202014160。呃，想通了，因为浮点运算的误差，-202014160这个结果是合理的。</p>
<p>为什么合理呢？很正常，因为上面的p3x和p2y是两个float类型，虽然v321是double，但也是两个float类型计算完后再转成double的，<strong>float的精度本来也只有7位，所以，对于这个上亿的数，自然没有办法保证精度</strong>。</p>
<p><strong>但是为什么修改CPU的type会有不同的效果？</strong>嗯，我们再试试C/C++。</p>
<p><span id="more-11235"></span></p>
<pre data-enlighter-language="c" class="EnlighterJSRAW">#include
using namespace std;

int main()
{
    float p3x = 80838.0f;
    float p2y = -2499.0f;
    double v321 = p3x * p2y;
    std::cout.precision(15);
    std::cout &lt;&lt; v321 &lt;&lt; std::endl;

    return 0;
}
</pre>
<p>上面这段C++代码在不同的平台下的结果如下：</p>
<ul>
<li>Windows 32/64位下：-202014160</li>
<li>Linux 64位下（CentOS 6 gcc 4.4.7）-202014160，</li>
<li>Linux 32位下（Ubuntu 12.04+ gcc 4.6.3）是：-202014162</li>
</ul>
<p><strong>合理的结果应该是-202014160，正确的运算结果是-202014162</strong>，合理性是浮点精度不够造成的（文后解释了合理性）。若是用两个double相乘可得正确且合理的运算结果（注：把上面C++的程序中的p3x和p2y的类型声明成double，就能得到正确的结果，因为double是双精度的，float是单精度，所以double有足够的位数存放更多的数位）。<strong>但是我们有点不明白，为什么Linux 32位下，居然能算出“正确”的数，而不是“合理”的数</strong>。</p>
<p>与C++一样，C#在32位和64位（DEBUG下，这个后面会说）下没有得到一致的结果，那我们来看一下C++/C#的汇编代码（使用gdb的disassemble /m main 命令，另外下面只显示 float * float 然后转成double的那一行代码的汇编）</p>
<p><strong>Linux平台下用G++编译</strong></p>
<pre data-enlighter-language="c" class="EnlighterJSRAW">//C++ 32位系统下 Ubuntu 12.04
8	    double v321 = p3x * p2y;
   0x0804860f &lt;+27&gt;:	flds   0x18(%esp)
   0x08048613 &lt;+31&gt;:	fmuls  0x1c(%esp)
   0x08048617 &lt;+35&gt;:	fstpl  0x10(%esp)

.......</pre>
<pre data-enlighter-language="c" class="EnlighterJSRAW">//C++ 64位系统下 CentOS 6
9           double v321 = p3x * p2y;
   0x000000000040083c &lt;+24&gt;:    movss  -0x20(%rbp),%xmm0
   0x0000000000400841 &lt;+29&gt;:    mulss  -0x1c(%rbp),%xmm0
   0x0000000000400846 &lt;+34&gt;:    unpcklps %xmm0,%xmm0
   0x0000000000400849 &lt;+37&gt;:    cvtps2pd %xmm0,%xmm0
   0x000000000040084c &lt;+40&gt;:    movsd  %xmm0,-0x18(%rbp)</pre>
<p><strong>Windows平台下用Visual Studio编译</strong></p>
<pre data-enlighter-language="c" class="EnlighterJSRAW">//C# AnyCPU编译，Windows VS2012
double v321 = p3x * p2y;
00000049  fld         dword ptr [ebp-40h]
0000004c  fmul        dword ptr [ebp-44h]
0000004f  fstp        qword ptr [ebp-4Ch]</pre>
<pre data-enlighter-language="c" class="EnlighterJSRAW">//C# X64位编译 Windows7 VS2012
double v321 = p3x * p2y;&lt;/pre&gt;
009B43B8 movss xmm0,dword ptr [p3x]
009B43BD mulss xmm0,dword ptr [p2y]
009B43C2 cvtss2sd xmm0,xmm0
009B43C6 movsd mmword ptr [v321],xmm0</pre>
<p>从上面的汇编代码可以看出，无论是Linux和Windows，C++或C# 32位和64对浮点数的汇编指令并不一样。 32位生成代码用的指令是fld/fmul/fstp等，而64位下的使用了movss/mulss/movsd/的指令。看下来，似乎这个事情和平台有关系。</p>
<p>我们继续调查，我们发现，其中fld/fmul/fstp等指令是由<strong>FPU</strong>(float point unit)浮点运算处理器做的，准确的说，是FPU x87指令，FPU在进行浮点运算时，用了<strong>80位</strong>的寄存器做相关浮点运算，然后再根据是float/double截取成32位或64位，FPU默认上会尽量减少由于需要四舍五入带来的精度问题。可参看浮点运算标准<a href="http://en.wikipedia.org/wiki/IEEE_floating_point" target="_blank">IEEE-754</a> 推荐标准实现者提供浮点可扩展精度格式(<a href="http://en.wikipedia.org/wiki/Extended_precision" target="_blank">Extended precision</a>)，Intel x86处理器有FPU(float point unit)浮点运算处理器支持这种扩展。</p>
<p>非FPU的情况是用了SSE中128位寄存器(float实际只用了其中的32位，计算时也是以32位计算的)，这就是导致上述问题产生的最终原因。详细分析见文末说明。</p>
<p>知道了这一点，我们可以man g++ 看一下文档，我们可以找到一个编译选项叫：<strong>-mfpmath，在32位下，这个编译选项的默认值是：387，也就是x87 FPU指令，在64位下，这个编译选项的值是sse，也就是使用SSE的指令</strong>。所以，就这篇文章中的这个例子而言，如果你在64bits下加上如 -mfpmath=387，你会得到“正确的”结果，而不是“合理的”结果。</p>
<p>而在VS2012中C++，<a href="http://msdn.microsoft.com/zh-cn/library/vstudio/e7s85ffb(v=vs.110).aspx" target="_blank">编译选项可以设置(代码生成中)</a>可选，/fp:[precise | fast | strict]，本例中Release 32位下用precise 或者 strict将得到合理的结果(-202014160)，fast将产生正确的结果(-202014162), fast debug/release下结果也不一样哦(release下才优化了)。64系统下各个结果可以大家自己去测试下(Debug/Release)，分别看看VS编译后产生的中间代码长什么样。（陈皓注：我的VS2012在debug编译下，无论你怎么设置/fp的参数值，汇编都是一样的，使用SSE指令，而Release就不一样了，但是我的release下看代码的汇编非常怪异和源代码对上号，多年不用Windows开发了，对VS的使用仅停留在VC6++/VC2005上）</p>
<p>所以，我们在从x87 FPU指令向SSE指令做代码移植的时候，我们可能会遇到向这样的浮点数的精度问题，这个精度问题会多次科学计算中会更糟糕。<strong>这个问题并不简单的只是在32位和64位中的系统出算，这个问题主要还是看语言编译器的实现</strong>。在更为高级的语言中，如：C99或Fortran 2003中，引入了“long double”来做可扩展双精度（Extension Double），这样就可以消除更多的精度问题。</p>
<p>下面我们把程序改成long double，（注：其中的类型变成long double）</p>
<pre data-enlighter-language="c" class="EnlighterJSRAW">#include
using namespace std;

int main()
{
    long double p3x = 80838.0;
    long double p2y = -2499.0;
    long double v321 = p3x * p2y;
    std::cout.precision(15);
    std::cout &lt;&lt; v321 &lt;&lt; std::endl;

    return 0;
}</pre>
<p>用gdb的disassemble /m main你会看到其中的运算的汇编如下（使用了fmlp指令）：</p>
<pre data-enlighter-language="c" class="EnlighterJSRAW">//linux 32位系统
8	    long double v321 = p3x * p2y;
   0x08048633 &lt;+63&gt;:	fldt   0x10(%esp)
   0x08048637 &lt;+67&gt;:	fldt   0x20(%esp)
   0x0804863b &lt;+71&gt;:	fmulp  %st,%st(1)
   0x0804863d &lt;+73&gt;:	fstpt  0x30(%esp)
</pre>
<pre data-enlighter-language="c" class="EnlighterJSRAW">//linux 64位系统
8           long double v321 = p3x * p2y;
   0x0000000000400818 &lt;+52&gt;:    fldt   -0x30(%rbp)
   0x000000000040081b &lt;+55&gt;:    fldt   -0x20(%rbp)
   0x000000000040081e &lt;+58&gt;:    fmulp  %st,%st(1)
   0x0000000000400820 &lt;+60&gt;:    fstpt  -0x10(%rbp)
</pre>
<p><span style="line-height: 1.5em;">我们可以看到，32位系统和64位系统使用了同样的汇编指令（当然，我没有那么多物理机，我只是在VMWare Play的虚拟机上测试的，所以上面的示例并不一定适用于所有的地方，另外，C/C++语言和编译器和平台有非常大的关系） ，原因自然是我们用到了long double这个扩展双精度的数据类型。（注：如果你用double或float，在Linux上，32位用x87 FPU 指令编译，而64位用SSE指令编译）</span></p>
<p>好了，我们再回到C#上来，<span style="line-height: 1.5em;">C#的浮点是支持该标准的，其中</span><a style="line-height: 1.5em;" href="http://msdn.microsoft.com/en-us/library/aa691146(v=vs.71).aspx">其官方文档</a><span style="line-height: 1.5em;">也提到了浮点运算可能会产生比返回类型更高精度的值（正如上面的返回值精度就超过了float的精度），并说明如果硬件支持可扩展浮点精度的话，那么</span><strong style="line-height: 1.5em;">所有的</strong><span style="line-height: 1.5em;">浮点运算都将用此精度进行以提高效率，举个例子x*y/z, x*y的值可能都在double的能力范围之外了，但真实情况可能除以z后又能把结果拉回到double范围内，这样的话，用了FPU的结果就会得到一个准确的double值，而非FPU的就是无穷大之类的了。</span></p>
<p><span style="line-height: 1.5em;">所以，对于</span>C#来说，你显然无法找到一个像C/C++一样的利用编译器选项的来解决这个问题的“解决方案”（其实，用编译器参数是一个伪解决方案）<span style="line-height: 1.5em;">。</span></p>
<p><span style="line-height: 1.5em;"><strong>而且，要解决这个问题也不是要修改编译器选项，因为这个问题明显不是FPU或是SSE的问题，FPU是个过时的技术，SSE才是合理的技术，所以，<span style="color: #cc0000;">如果你不想你的浮点数在计算上有什么问题，而且你需要精度准确，正确的解决方案不是搞编译参数，而是——你一定要使用精度更高字节数更多的数据类型，比如：double 或是long double</span>。</strong></span></p>
<p>另外，大家在写代码的时候得保证实际运行环境/测试环境/开发环境的<strong>一致性(包括OS架构啊、编译选项等)</strong>啊（<strong>尤其是C/C++ 而且，编译器上的参数可能会有很多坑，而且有些坑可能会掩盖你程序中的问题</strong>），不然莫名其妙的问题会产生（本文就是开发环境与运行环境不一致导致的问题，纠结了好久才发现是这个原因）；遇到涉及浮点运算的时候别忘了有可能是这个原因产生的；<strong>float/double混用的情况得特别注意</strong>。</p>
<p><strong>Reference：</strong></p>
<p>[1] <a href="http://msdn.microsoft.com/en-us/library/aa691146(v=vs.71).aspx">C# Language Specification Floating point types</a><br />
[2] <a href="http://stackoverflow.com/questions/6683059/are-floating-point-numbers-consistent-in-c-can-they-be">Are floating-point numbers consistent in C#? Can they be? </a><br />
[3] <a href="http://www.plantation-productions.com/Webster/www.artofasm.com/Linux/HTML/RealArithmetica2.html">The FPU Instruction Set</a></p>
<h4><strong>附录</strong></h4>
<h5><strong>80838.0f * -2499.0f = -202014160.0浮点运算过程的说明</strong></h5>
<p>32位浮点数在计算机中的表示方式为：1位符号位(s)-8位指数位(E)-23位有效数字(M)。<br />
32位Float = (-1)^s * (1+m) * 2^(e-127), 其中e是实际转换成1.xxxxx*2^e的指数,m是前面的xxxxx(节约1位)</p>
<p>80838.0f = 1 0011 1011 1100 0110.0= 1.00111011110001100*2^16<br />
有效位M = 0011 1011 1100 0110 0000 000<br />
指数位E = 16 + 127 = 143 =  10001111<br />
内部表示 80838.0 =  0 [1000 1111] [0011 1011 1100 0110 0000 000]<br />
= 0100 0111 1001 1101 1110 0011 0000 0000<br />
= 47 9d e3 00 //实际调试时看到的内存值 可能是00 e3 9d 47是因为调试环境用了小端表示法法：低位字节排内存低地址端，高位排内存高地址</p>
<p>-2499.0 = -100111000011.0 = -1.001110000110 * 2^11<br />
有效位M = 0011 1000 0110 0000 0000 000<br />
指数位E = 11+127=138= 10001010<br />
符号位s = 1<br />
内部表示-2499.0 = 1 [10001010] [0011 1000 0110 0000 0000 000]<br />
=1100 0101 0001 1100 0011 0000 0000 0000<br />
=c5 1c 30 00</p>
<p>80838.0 * -2499.0 = ?</p>
<p>首先是指数 e = 11+16 = 27<br />
指数位E = e + 127 = 154 = 10011010<br />
有效位相乘结果为 1.1000 0001 0100 1111 1011 1010 01 //可以自己动手实际算下<br />
实际中只能有23位，后面的被截断即1000 0001 0100 1111 1011 101<span style="text-decoration: line-through;">0 01 </span><br />
相乘结果内部表示=1[10011010][1000 0001 0100 1111 1011 101]<br />
= 1100 1101 0100 0000 1010 0111 1101 1101<br />
= cd 40 a7 dd</p>
<p>结果 =  -1.1000 0001 0100 1111 1011 101 *2^27<br />
=  -11000 0001 0100 1111 1011 1010000<br />
=  -202014160<br />
再转成double后还是-202014160.</p>
<p>如果是FPU的话，上面的有效位结果不会被截断，即<br />
FPU结果 = -1.1000 0001 0100 1111 1011 101<strong>001</strong> *2^27<br />
= -11000 0001 0100 1111 1011 101<strong>001</strong>0<br />
= -202014162</p>
<p>全文完，若本文有纰漏之处欢迎指正。<!--



<p align="center"><a href= target=_blank><img decoding="async" src=""></a></p>





<p align="center"><img decoding="async" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"> <img decoding="async" loading="lazy" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300" height="300"> <br />关注CoolShell微信公众账号和微信小程序</p>

 

--></p>
<div style="margin-top: 15px; font-size: 16px;color: #cc0000;">
<p align="center"><strong>（转载本站文章请注明作者和出处 <a href="https://coolshell.cn/">酷 壳 &#8211; CoolShell</a> ，请勿用于任何商业用途）</strong></p>
</div>

<div class="wp_rp_wrap  wp_rp_vertical_m" id="wp_rp_first"><div class="wp_rp_content"><h3 class="related_post_title">相关文章</h3><ul class="related_post wp_rp"><li ><a href="https://coolshell.cn/articles/3008.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/10.jpg" alt="Windows编程革命简史" width="150" height="150" /></a><a href="https://coolshell.cn/articles/3008.html" class="wp_rp_title">Windows编程革命简史</a></li><li ><a href="https://coolshell.cn/articles/2672.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/0.jpg" alt=".NET代码转换器" width="150" height="150" /></a><a href="https://coolshell.cn/articles/2672.html" class="wp_rp_title">.NET代码转换器</a></li><li ><a href="https://coolshell.cn/articles/20845.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2020/03/rust-social-wide-150x150.jpg" alt="Rust语言的编程范式" width="150" height="150" /></a><a href="https://coolshell.cn/articles/20845.html" class="wp_rp_title">Rust语言的编程范式</a></li><li ><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2018/05/300x262-150x150.jpg" alt="程序员练级攻略（2018)  与我的专栏" width="150" height="150" /></a><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_title">程序员练级攻略（2018)  与我的专栏</a></li><li ><a href="https://coolshell.cn/articles/18024.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2017/07/api-design-300x278-2-150x150.jpg" alt="API设计原则 &#8211; Qt官网的设计实践总结" width="150" height="150" /></a><a href="https://coolshell.cn/articles/18024.html" class="wp_rp_title">API设计原则 &#8211; Qt官网的设计实践总结</a></li><li ><a href="https://coolshell.cn/articles/12052.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/29.jpg" alt="Leetcode 编程训练" width="150" height="150" /></a><a href="https://coolshell.cn/articles/12052.html" class="wp_rp_title">Leetcode 编程训练</a></li></ul></div></div>The post <a href="https://coolshell.cn/articles/11235.html">一个浮点数跨平台产生的问题</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></content:encoded>
					
					<wfw:commentRss>https://coolshell.cn/articles/11235.html/feed</wfw:commentRss>
			<slash:comments>25</slash:comments>
		
		
			</item>
		<item>
		<title>Windows编程革命简史</title>
		<link>https://coolshell.cn/articles/3008.html</link>
					<comments>https://coolshell.cn/articles/3008.html#comments</comments>
		
		<dc:creator><![CDATA[陈皓]]></dc:creator>
		<pubDate>Mon, 27 Sep 2010 00:51:30 +0000</pubDate>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[轶事趣闻]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ActiveX]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[DDE]]></category>
		<category><![CDATA[J++]]></category>
		<category><![CDATA[OLE]]></category>
		<guid isPermaLink="false">http://coolshell.cn/?p=3008</guid>

					<description><![CDATA[<p>源文：A Brief History of Windows Programming Revolutions （Ron Burk） 首先，是 Windows AP...</p>
<p class="read-more"><a class="btn btn-default" href="https://coolshell.cn/articles/3008.html"> Read More<span class="screen-reader-text">  Read More</span></a></p>
The post <a href="https://coolshell.cn/articles/3008.html">Windows编程革命简史</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></description>
										<content:encoded><![CDATA[<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415450859608158"
     crossorigin="anonymous"></script>源文：<a href="http://www.drdobbs.com/windows/225701475" target="_blank">A Brief History of Windows Programming Revolutions</a> （Ron Burk）</p>
<p>首先，是 Windows API 和 <a href="http://en.wikipedia.org/wiki/DLL_hell" target="_blank">DLL Hell</a>。（译注：DLL Hell——DLL灾难，就是微软的DLL升级时因为不同版本可能造成应用程序无法运行的灾难，首当其冲的是COM编程，相信大家都知道某些木马或是病毒更改了一些系统的DLL可以导致整个Windows不举，这就是DLL Hell） 于是，第一次革命是<a href="http://en.wikipedia.org/wiki/Dynamic_Data_Exchange" target="_blank">DDE</a>——我们可以创建一个状态条在上面显示Microsoft的股票价格（译注：Dynamic Data Exchange，工作原理是： 甲方申请一块全局内存，然后把内存指针postmessage到乙方，乙方根据收到的指针访问那块全局内存）。</p>
<p>在那个时候，Microsoft 创建了 VERSIONINFO 资源来管理版本信息，当然，是用来消除DLL Hell。但是，另一个微软内部的小组发现了DDE的致命缺陷：这不是他们做的！</p>
<p>为了解决这个问题，他们创造了OLE（很像DDE，只是名字不一样），而且，我还记得在一次 Microsoft 大会上，某个微软的演讲者正式宣布—— Windows API 马上就会被 OLE API 所重写并取代，我还盲目地相信了这一说法。而且，所有的在图形界面的控件都会是OCX，那是OLE引入的接口，同样，其目的是为了消除DLL Hell。相信大家都记得，那个时候，我们是怎么地梦想着有一天，我们的应用程序（当然是非常大的程序）可以完全地被嵌入到Word文档中。</p>
<p>然而，在Microsoft的某处，Microsoft有些人开始信仰 C++，其确信MFC的出现并可以解决所有的一切问题，但是，因为历史原因，OLE并没有出局，其改了一个名字，叫COM，此时，我们立马意识到OLE（以前的DDE？）真正意味着什么——其用精心的版本管理系统来消除DLL Hell。与此同时，Microsoft的一个变节小组发现了一个MFC的致命缺陷：这不是他们做的！</p>
<p><span id="more-3008"></span></p>
<p>当然，微软件的动作是很快的，他们立刻修正了问题——创造了ATL，有些像MFC，只是名字不同，他们想使用漂亮的ATL把那些晦涩难懂的COM的知识给隐藏住。这个动作刺激了COM团队（或是OLE团队？）改名为ActiveX，并发布了成千上万的新接口（甚至是很多版本化的接口，当然，主要目的是为了消除DLL Hell），当然，ActiveX可以让我们的程序可以从Web游览器上下载，并可以完美地和病毒一起嵌入浏览器中（哈，还不紧跟时代，感谢ATL吧）。此时，操作系统团队就像一个失宠的孩子一样，大声呼喊着“<a href="http://www.microsoft.com/middleeast/egypt/cmic/" target="_blank">Cairo操作系统</a>来了”引起大家注意，当然有一些怪异恶心的东西连他们自己也无法解释清楚，所以，别提发布了。为了声誉，操作系统团队的确引入了“系统文件保护”的理念，当然也是为了消除DLL Hell。</p>
<p>这个时候，Microsoft的某个团队发现了Java的致命缺陷：这不是他们做的！于是他们创造了一个叫J，或是Jole，或是ActiveJ的东西（对不起，我真的记不起叫什么了）来挽救Java（译者：应该是Visual J++）。看起来很像Java，只是名字不同罢了。这太让人兴奋了，但是Sun使用了一些相当古老的法律条款向Microsoft提起了法律诉讼，其在一年内限制了任何一个公司可以发布类似Java的产品。这明显是抑制微软复制别人产品的一次尝试，唯一不同的，其结果导致了微软流向国会议员裤兜的现金网络的建立（在这个网络可以得到时事新闻和价值$14.75的T恤衫）。还记得 J/Jole/ActiveJ 的项目经理用他的鞋桌在敲着桌子并信誓旦旦地坚持 Microsoft 将永远不会放弃他的产品。SB！所有的这些也就仅仅意味着一件事——没有人关心ActiveX团队（或者是COM？）。令人难以置信的是，微软把这些东东全部集成起来，成了COM+（难道不应该是ActiveX+?），还有MTS（我不知道为什么没有COM和Active或是X或是+的字眼，而直接叫MTS了——我为这个名词感到实实在在地震惊！）。他们总是那么NB地为那些流行词加上“+”号。在那段时间，还有人曾叫喊着“Windows DNA”以及“Windows Washboard”，但这两个东西最终在我搞清是什么玩意的之前就夭折了。</p>
<p>在这一点上，Microsoft已经很不安地窥视着Internet好几年了，他们终于意识到Internet上有一个致命缺陷：嗯，你应该知道这是什么（译注：Internet不是做他们做的！）。于是他们开始培养我们和.NET约会（.NET的发音很像“doughnut”圆环图，不过，这只是他们的唯一不同），这和Internet很相似，只不过.NET有更多的印刷品。其让我们清楚再清楚地了解一件事：.NET会消除DLL Hell。.NET包含了一个新的编程语言，叫C#（为了解决已经死翘翘的Active++ J++的缺陷）。.NET还包含一个虚拟机，所有的语言都运行在上面（这主要是为了解决依赖于Intel CPU的缺陷）。.NET还包含了一个单一的登录系统（这主要是为了解决“不把口令存放在Microsoft服务器上”的缺陷）。实际上，我们更容易做的是把.NET不包含的事给列出来。.NET绝对是一个划时代地Windows编程革命……当然，仅到明年。</p>
<p>（全文完）<!--



<p align="center"><a href= target=_blank><img decoding="async" src=""></a></p>





<p align="center"><img decoding="async" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"> <img decoding="async" loading="lazy" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300" height="300"> <br />关注CoolShell微信公众账号和微信小程序</p>

 

--></p>
<div style="margin-top: 15px; font-size: 16px;color: #cc0000;">
<p align="center"><strong>（转载本站文章请注明作者和出处 <a href="https://coolshell.cn/">酷 壳 &#8211; CoolShell</a> ，请勿用于任何商业用途）</strong></p>
</div>

<div class="wp_rp_wrap  wp_rp_vertical_m" ><div class="wp_rp_content"><h3 class="related_post_title">相关文章</h3><ul class="related_post wp_rp"><li ><a href="https://coolshell.cn/articles/11235.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/2.jpg" alt="一个浮点数跨平台产生的问题" width="150" height="150" /></a><a href="https://coolshell.cn/articles/11235.html" class="wp_rp_title">一个浮点数跨平台产生的问题</a></li><li ><a href="https://coolshell.cn/articles/4102.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/25.jpg" alt="如何学好C语言" width="150" height="150" /></a><a href="https://coolshell.cn/articles/4102.html" class="wp_rp_title">如何学好C语言</a></li><li ><a href="https://coolshell.cn/articles/2672.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/0.jpg" alt=".NET代码转换器" width="150" height="150" /></a><a href="https://coolshell.cn/articles/2672.html" class="wp_rp_title">.NET代码转换器</a></li><li ><a href="https://coolshell.cn/articles/20845.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2020/03/rust-social-wide-150x150.jpg" alt="Rust语言的编程范式" width="150" height="150" /></a><a href="https://coolshell.cn/articles/20845.html" class="wp_rp_title">Rust语言的编程范式</a></li><li ><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2018/05/300x262-150x150.jpg" alt="程序员练级攻略（2018)  与我的专栏" width="150" height="150" /></a><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_title">程序员练级攻略（2018)  与我的专栏</a></li><li ><a href="https://coolshell.cn/articles/18024.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2017/07/api-design-300x278-2-150x150.jpg" alt="API设计原则 &#8211; Qt官网的设计实践总结" width="150" height="150" /></a><a href="https://coolshell.cn/articles/18024.html" class="wp_rp_title">API设计原则 &#8211; Qt官网的设计实践总结</a></li></ul></div></div>The post <a href="https://coolshell.cn/articles/3008.html">Windows编程革命简史</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></content:encoded>
					
					<wfw:commentRss>https://coolshell.cn/articles/3008.html/feed</wfw:commentRss>
			<slash:comments>239</slash:comments>
		
		
			</item>
		<item>
		<title>.NET代码转换器</title>
		<link>https://coolshell.cn/articles/2672.html</link>
					<comments>https://coolshell.cn/articles/2672.html#comments</comments>
		
		<dc:creator><![CDATA[陈皓]]></dc:creator>
		<pubDate>Tue, 20 Jul 2010 02:24:22 +0000</pubDate>
				<category><![CDATA[.NET编程]]></category>
		<category><![CDATA[杂项资源]]></category>
		<category><![CDATA[编程工具]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[VB.NET]]></category>
		<guid isPermaLink="false">http://coolshell.cn/?p=2672</guid>

					<description><![CDATA[<p>想把.NET的代码（C#和VB.NET)互转吗？或是转成Python或Ruby吗？在 http://www.developerfusion.com/ 站点上有这...</p>
<p class="read-more"><a class="btn btn-default" href="https://coolshell.cn/articles/2672.html"> Read More<span class="screen-reader-text">  Read More</span></a></p>
The post <a href="https://coolshell.cn/articles/2672.html">.NET代码转换器</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></description>
										<content:encoded><![CDATA[<p><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3415450859608158"
     crossorigin="anonymous"></script>想把.NET的代码（C#和VB.NET)互转吗？或是转成Python或Ruby吗？在 <a href="http://www.developerfusion.com/" target="_blank">http://www.developerfusion.com/</a> 站点上有这样的在线工具。点击下面的链接你可以使用这些工具。当然，这些工具也有很多<a href="http://feedback.developerfusion.com/pages/code_converter" target="_blank">BUG</a>。</p>
<ul>
<li><a href="http://www.developerfusion.com/tools/convert/csharp-to-vb/" target="_blank">把 C# 转成 VB.NET</a></li>
<li><a href="http://www.developerfusion.com/tools/convert/csharp-to-python/" target="_blank">把 C# 转成 Python</a></li>
<li><a href="http://www.developerfusion.com/tools/convert/csharp-to-ruby/" target="_blank">把 C# 转成Ruby</a></li>
<li><a href="http://www.developerfusion.com/tools/convert/vb-to-csharp/" target="_blank">把 VB.NET 转成C#</a></li>
<li><a href="http://www.developerfusion.com/tools/convert/vb-to-python/" target="_blank">把 VB.NET 转成 Python</a></li>
<li><a href="http://www.developerfusion.com/tools/convert/vb-to-ruby/" target="_blank">把 VB.NET 转成 Ruby</a></li>
</ul>
<p>老实说，我并不太清楚这些工具有什么用，看似很useless。难道是为了用来学习新的语言？就像Google的Translator的一样？就像一个并不懂中文的老外可以用Google Translator在其Facebook中整点中文耍耍酷一样，难道说，一个C#的程序员可以用这样的工具和一个Python的程序员也耍耍酷？各位看客觉得这个东西有意义吗？</p>
<p>不过，有一点我可以确定，如果有工具把Unix/Linux下的C源码和Windows下的C源码相互自动转换，估计这会是相当划时代的，因为，这应该会让那些什么Wine或Cygwin之类的东西都统统会成为历史了。不过，这样的东西在实现上又将会有多么大的难度（OS系统API的相互转换），这个事会有可行性吗？<!--



<p align="center"><a href= target=_blank><img decoding="async" src=""></a></p>





<p align="center"><img decoding="async" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.weixin.jpg"> <img decoding="async" loading="lazy" src="https://coolshell.cn/wp-content/uploads/2020/03/coolshell.mini_.jpg" width="300" height="300"> <br />关注CoolShell微信公众账号和微信小程序</p>

 

--></p>
<div style="margin-top: 15px; font-size: 16px;color: #cc0000;">
<p align="center"><strong>（转载本站文章请注明作者和出处 <a href="https://coolshell.cn/">酷 壳 &#8211; CoolShell</a> ，请勿用于任何商业用途）</strong></p>
</div>

<div class="wp_rp_wrap  wp_rp_vertical_m" ><div class="wp_rp_content"><h3 class="related_post_title">相关文章</h3><ul class="related_post wp_rp"><li ><a href="https://coolshell.cn/articles/11235.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/2.jpg" alt="一个浮点数跨平台产生的问题" width="150" height="150" /></a><a href="https://coolshell.cn/articles/11235.html" class="wp_rp_title">一个浮点数跨平台产生的问题</a></li><li ><a href="https://coolshell.cn/articles/3192.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2010/10/Intel-Recommended-Books-for-Developers-150x150.jpg" alt="一些非常不错的资料" width="150" height="150" /></a><a href="https://coolshell.cn/articles/3192.html" class="wp_rp_title">一些非常不错的资料</a></li><li ><a href="https://coolshell.cn/articles/3008.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/plugins/wordpress-23-related-posts-plugin/static/thumbs/10.jpg" alt="Windows编程革命简史" width="150" height="150" /></a><a href="https://coolshell.cn/articles/3008.html" class="wp_rp_title">Windows编程革命简史</a></li><li ><a href="https://coolshell.cn/articles/20845.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2020/03/rust-social-wide-150x150.jpg" alt="Rust语言的编程范式" width="150" height="150" /></a><a href="https://coolshell.cn/articles/20845.html" class="wp_rp_title">Rust语言的编程范式</a></li><li ><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2018/05/300x262-150x150.jpg" alt="程序员练级攻略（2018)  与我的专栏" width="150" height="150" /></a><a href="https://coolshell.cn/articles/18360.html" class="wp_rp_title">程序员练级攻略（2018)  与我的专栏</a></li><li ><a href="https://coolshell.cn/articles/18024.html" class="wp_rp_thumbnail"><img src="https://coolshell.cn/wp-content/uploads/2017/07/api-design-300x278-2-150x150.jpg" alt="API设计原则 &#8211; Qt官网的设计实践总结" width="150" height="150" /></a><a href="https://coolshell.cn/articles/18024.html" class="wp_rp_title">API设计原则 &#8211; Qt官网的设计实践总结</a></li></ul></div></div>The post <a href="https://coolshell.cn/articles/2672.html">.NET代码转换器</a> first appeared on <a href="https://coolshell.cn">酷 壳 - CoolShell</a>.]]></content:encoded>
					
					<wfw:commentRss>https://coolshell.cn/articles/2672.html/feed</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
	</channel>
</rss>
