Why does quot;dtoa.cquot; contain so much code?(为什么“dtoa.c包含这么多代码?)
问题描述
我将是第一个承认我对低级编程的整体知识有点稀疏的人.我了解许多核心概念,但我不经常使用它们.话虽如此,我对 dtoa.c 需要多少代码感到非常震惊.
I'll be the first to admit that my overall knowledge of low level programming is a bit sparse. I understand many of the core concepts but I do not use them on a regular basis. That being said I was absolutely astounded at how much code was needed for dtoa.c.
在过去的几个月里,我一直致力于 C# 中的 ECMAScript 实现,我一直在减慢填补引擎中的漏洞.昨晚我开始研究 15.7.4.2 部分中描述的 Number.prototype.toString#x15.7.4.2" rel="noreferrer">ECMAScript 规范 (pdf).在 9.8.1 部分,NOTE 3 提供了一个到 dtoa.c 的链接,但我正在寻找一个挑战,所以我等待查看它.以下是我想出的.
For the past couple months I have been working on an ECMAScript implementation in C# and I've been slowing filling in the holes in my engine. Last night I started working on Number.prototype.toString which is described in section 15.7.4.2 of the ECMAScript specification (pdf). In section 9.8.1, NOTE 3 offers a link to dtoa.c but I was looking for a challenge so I waited to view it. The following is what I came up with.
private IDynamic ToString(Engine engine, Args args)
{
var thisBinding = engine.Context.ThisBinding;
if (!(thisBinding is NumberObject) && !(thisBinding is NumberPrimitive))
{
throw RuntimeError.TypeError("The current 'this' must be a number or a number object.");
}
var num = thisBinding.ToNumberPrimitive();
if (double.IsNaN(num))
{
return new StringPrimitive("NaN");
}
else if (double.IsPositiveInfinity(num))
{
return new StringPrimitive("Infinity");
}
else if (double.IsNegativeInfinity(num))
{
return new StringPrimitive("-Infinity");
}
var radix = !args[0].IsUndefined ? args[0].ToNumberPrimitive().Value : 10D;
if (radix < 2D || radix > 36D)
{
throw RuntimeError.RangeError("The parameter [radix] must be between 2 and 36.");
}
else if (radix == 10D)
{
return num.ToStringPrimitive();
}
var sb = new StringBuilder();
var isNegative = false;
if (num < 0D)
{
isNegative = true;
num = -num;
}
var integralPart = Math.Truncate(num);
var decimalPart = (double)((decimal)num.Value - (decimal)integralPart);
var radixChars = RadixMap.GetArray((int)radix);
if (integralPart == 0D)
{
sb.Append('0');
}
else
{
var integralTemp = integralPart;
while (integralTemp > 0)
{
sb.Append(radixChars[(int)(integralTemp % radix)]);
integralTemp = Math.Truncate(integralTemp / radix);
}
}
var count = sb.Length - 1;
for (int i = 0; i < count; i++)
{
var k = count - i;
var swap = sb[i];
sb[i] = sb[k];
sb[k] = swap;
}
if (isNegative)
{
sb.Insert(0, '-');
}
if (decimalPart == 0D)
{
return new StringPrimitive(sb.ToString());
}
var runningValue = 0D;
var decimalIndex = 1D;
var decimalTemp = decimalPart;
sb.Append('.');
while (decimalIndex < 100 && decimalPart - runningValue > 1.0e-50)
{
var result = decimalTemp * radix;
var integralResult = Math.Truncate(result);
runningValue += integralResult / Math.Pow(radix, decimalIndex++);
decimalTemp = result - integralResult;
sb.Append(radixChars[(int)integralResult]);
}
return new StringPrimitive(sb.ToString());
}
谁能解释一下为什么 dtoa.c 有大约 40 倍的代码?我简直无法想象 C# 会变得如此高效.
Can anyone with more experience in low level programming explain why dtoa.c has roughly 40 times as much code? I just cannot imagine C# being that much more productive.
推荐答案
dtoa.c 包含两个主要函数:dtoa() 将双精度数转换为字符串,strtod() 将字符串转换为双精度数.它还包含很多支持函数,其中大部分是针对它自己的任意精度算术实现的.dtoa.c 声名鹊起的是正确地进行这些转换,而这通常只能通过任意精度的算术来完成.它还具有在四种不同舍入模式下正确舍入转换的代码.
dtoa.c contains two main functions: dtoa(), which converts a double to string, and strtod(), which converts a string to a double. It also contains a lot of support functions, most of which are for its own implementation of arbitrary-precision arithmetic. dtoa.c's claim to fame is getting these conversions right, and that can only be done, in general, with arbitrary-precision arithmetic. It also has code to round conversions correctly in four different rounding modes.
您的代码仅尝试实现 dtoa() 的等价物,并且由于它使用浮点进行转换,因此并不总是正确的.(更新:见我的文章 http://www.explorebinary.com/quick-and-dirty-floating-point-to-decimal-conversion/ 了解详情.)
Your code only tries to implement the equivalent of dtoa(), and since it uses floating-point to do its conversions, will not always get them right. (Update: see my article http://www.exploringbinary.com/quick-and-dirty-floating-point-to-decimal-conversion/ for details.)
(我在我的博客上写了很多关于此的内容,http://www.exploringbinary.com/.我过去的七篇文章中有六篇都是关于 strtod() 转换的.通读它们以了解正确舍入转换是多么复杂.)
(I've written a lot about this on my blog, http://www.exploringbinary.com/ . Six of my last seven articles have been about strtod() conversions alone. Read through them to see how complicated it is to do correctly rounded conversions.)
这篇关于为什么“dtoa.c"包含这么多代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么“dtoa.c"包含这么多代码?
基础教程推荐
- 将 XML 转换为通用列表 2022-01-01
- 如何在 IDE 中获取 Xamarin Studio C# 输出? 2022-01-01
- rabbitmq 的 REST API 2022-01-01
- 将 Office 安装到 Windows 容器 (servercore:ltsc2019) 失败,错误代码为 17002 2022-01-01
- 如何激活MC67中的红灯 2022-01-01
- 有没有办法忽略 2GB 文件上传的 maxRequestLength 限制? 2022-01-01
- 为什么Flurl.Http DownloadFileAsync/Http客户端GetAsync需要 2022-09-30
- MS Visual Studio .NET 的替代品 2022-01-01
- c# Math.Sqrt 实现 2022-01-01
- SSE 浮点算术是否可重现? 2022-01-01