是否存在不能以10为基数但可以以2为基数的数字?


42

C#decimal类型用于需要以10为底的精确表示的数字。例如,0.1不能以2为底(例如floatdouble)表示,并且在存储在这些类型的变量中时始终为近似值。

我想知道相反的事实是否还可能。是否存在以10为基数不能表示但可以以2为基数表示的数字(在这种情况下,我想使用a float代替a decimal来处理它们)?


14
为问题+1,但是c#标记在这里真的适用吗?其他语言也具有十进制类型。
Patrick M

1
@Max:作为练习,我建议您想象一下手动将以2为底的数字转换为以10为底的数字。例如,要计算的值0.11_b2,请将其写为0.5 + 0.5 * 0.5。是否有可能失败或导致重复小数的任何步骤?就个人而言,我发现此练习在了解以2为底的数字的直觉上做得很好。我想可以再进一步一步,将这一练习转变为一种证明。
布莱恩

啊,但是你错了。1/10/10
Xavier J

3
@Ramhound在给定的内存限制下,二进制可以0.0999999....998..精确地表示,但不能表示完整的数字0.1-类似于四舍五入到最接近的百分位数的近似值0.100是实现方面的关注点,涉及到不显示所有数字并将其四舍五入。
Izkata 2014年

1
好吧,有可能想出一种FP编码机制,该机制可以精确地表示“ 0.1”。这样的编码仅在FP编号范围的集合周围移动,而不可以表示。
马丁·詹姆斯

Answers:


104

这里的关键是你的困惑:10是的产品25。可以表示任何数量的恰好在底座10个小数即K * 1/2 Ñ * 1/5 ,其中knm是整数。

换句话说-如果n1 / n中的数字包含一个不属于基数因子的因数,则该数字将不能以固定数量的数字准确地以二进制,十进制或该数字的任何扩展形式表示数字-它会有重复的部分。例如1/15 = 0.0666666666 ....因为3(15 = 3 * 5)不是10的因数。

因此,任何能够在基数2中精确表示的东西(k * 1/2 n)都可以在基数10中精确表示。

除此之外,还有一个问题是您要使用多少个数字/位来代表数字。有一些数字可以在某个基数中准确表示,但是要做的事情不止一些数字/位。


在二进制中,数字1/10(通常为十进制的0.1)不能表示为可以用固定位数的二进制形式表示的数字。相反,该数字为0.00011001100110011 ... 2(0011部分将永远重复)。

让我们来看看数1 2 /1010 2位更加紧密。

          ____                  
       0.00011                  
     + ---------                 
1010 | 1.00000                  
       0                        
       -                       
       1 0                      
         0                      
       ----                     
       1 00 --------- +          
          0 |          
       ----- |          
       1 000 |          
           0 |          
       ------ | 重复
       1 0000 | 块    
         1010 |          
       ------ |          
          1100 |          
          1010 |          
          ---- |          
            100 ---- +          

这与尝试进行1/3的长除法时得到的类型完全相同。

当分解为1 /(2 1 * 5 1)时为1/10 。对于以10为底的数字(或10的任意倍数),此数字终止,称为常规数字。重复的十进制扩展称为重复的十进制,那些永远不重复的数字就是无理数。

背后数学探究了Fermat的小定理 ...一旦您开始说Fermat或定理,它便成为Math.SE问题

是否存在不能以10为基数但可以以2为基数的数字?

答案是不'。

因此,在这一点上我们都应该清楚,有理数的每个固定长度的二进制扩展都可以表示为固定长度的十进制扩展。


让我们更仔细地看一下C#中的十进制,这导致我们到达.NET中的Decimal浮点,并且在作者看来,我接受那就是它的工作原理。

十进制类型与其他任何浮点数具有相同的组成部分:尾数,指数和符号。像往常一样,符号只是一位,但尾数为96位,指数为5位。但是,并非所有指数组合都是有效的。只有值0-28有效,并且它们实际上都是负数:数值是。这意味着该类型的最大值和最小值为+/-(2 96 -1),并且就绝对大小而言,最小的非零数为10 -28sign * mantissa / 10exponent

我将立即指出,由于此实现,double类型中的某些数字无法表示decimal-超出范围的数字。 Double.Epsilon4.94065645841247e-324不能用表示decimal,但可以用表示double

但是,在十进制可以表示的范围内,它比其他本机类型具有更高的精度位,并且可以无错误地表示它们。

还有其他一些类型。C#中有一个BigInteger,它可以表示任意大的整数。没有相当于Java的BigDecimal的(其可以表示数字最多高达2的十进制数字32位长-这是一个相当大的范围)完全相同。但是,如果您四处摸索,则可以找到手动实现。

有些语言也具有有理数据类型,可让您精确表示有理(因此1/3实际上是1/3)。


具体来说,对于C#和float或有理数的选择,我将从.NET中Decimal浮动pint转到Jon Skeet :

大多数业务应用程序可能应该使用小数而不是浮点数或双精度数。我的经验法则是,通常用十进制浮点数更好地表示诸如货币之类的人造值:例如,精确地1.25美元的概念是完全合理的。对于自然界的值(例如长度和权重),二进制浮点类型更有意义。即使理论上“精确地达到1.25米”,它也永远不会发生:您当然永远也无法测量精确的长度,并且它们甚至不可能出现在原子级。我们已经习惯了一定的容忍度。


+1可提供简洁明了的数学解释。为了回答标题中提出的问题的更一般版本,以10为基数无法表示的数字的示例为1/3。
Doval 2014年

@Doval我确实怀疑我的推理或解释中存在一个小故障,即更倾向于数学的人可能会指出...但我确实认为,在这种情况下,我处于正确的轨道。

在这种情况下,“相对质数”仅表示“不是因素”,对吗?我缺少更深层次的数学关系吗?
Patrick M

1
嗯,据我所知,n = 15并且b = 10不是相对质数(“除1外,没有其他共同的积极因素(除数)”),因为它们共享5作为因素。关键在于,并非所有的15因子(5 3)都不都是10因子。(此外:是否有一个词来表示那些共享或不共享所有公共因子的数字?)我认为这很简洁包裹在您的k, n, m方程中,但是要真正绕开它,我需要查看3d图。无论如何,您应得的+1。
Patrick M

1
@PatrickM:“在旁边:是否有一个词来表示可以共享或不共享所有公共因子的数字?”:任何整数都是其自身的因子,因此,如果m的所有因子都是n的因子,那么它的含义就很简单。mn的因数。正如您所清楚地知道的那样,因素之一就是factor。另一个是除数
ruakh 2014年

6

一旦超出可接受的值范围,答案是肯定的。也就是说,范围内的几乎所有内容都将具有表示形式。C#十进制参考尽管在规范中未作说明,但不能精确表示无理数(例如e 1,pi,2的平方根等)。

十进制关键字表示128位数据类型。与浮点类型相比,十进制类型具有更高的精度和更小的范围,这使其适用于财务和货币计算。下表显示了十进制类型的近似范围和精度。

精度:28-29位有效数字

1感谢MichaelT使我想起另一个不合理的数字。


2
@Magus考虑无理数e(2.71 ...)。自然对数ln(x)是对数e。因此,不合理的基础确实存在并且是有用的。我不确定基本pi的特殊用途-但这并不意味着它没有在某处使用。

6
@Max,您越来越迷失于数学问题。您可能会发现,如果一个数字在10的底数中是不合理的,那么在其他的基数中它是否不合理?成为有用的读物​​,也是更多数论问题的起点。

2
1/3并非非理性。
亚当·祖克曼

2
OP询问了以10为底的数字(十)。以数字为基数可以使您将任何内容表示为10。根据Wikipedia的文章,使用无理数作为基数并不能使其合理。有理数可以表示为分子和分母的整数,以小数形式重复数字,或以小数形式有限地终止。
亚当·祖克曼

5
@FrustratedWithFormsDesigner不合理性与基础无关。好吧,这是一个夸大的说法,但是不合理性影响了数字在各种基础中的表示形式(例如,它是否具有无限的非重复数字),而不是相反。阅读链接至上述math.se问题:math.stackexchange.com/questions/625473/...

1

基数为二的浮点类型将能够精确表示许多相同大小的基数为十的类型不能表示的值。用某种大小的以2为底的类型可以精确表示的任何值都可以以足够大小的以10为底的类型来精确表示。纯粹十进制类型表示二进制浮点数的所有值所需的大小将取决于二进制类型的指数范围。数百个比特float或数千个比特double

话虽Decimal这么说,该类型足够大,以致有可能使它能够用作“通用”类型,该类型能够保存任何其他数字基元的值并提供其他一些附加功能(如果没有其他用途,请使用一位指示存储的值是否是对进行转换的结果double,如果该位被设置,请使用64位保存所讨论的值)。微软选择不这样做。其结果是,一个转换doubleDecimal将完全失败大的值,将导致小的值被四舍五入到最近的1E-28。此外,即使在动态范围内decimal,转换方法将不会“往返”。例如,将1.0 / 3.0评估为两倍将得到0.3333333333333333148,但是将其转换为十进制将产生0.333333333333333m,将其转换为双倍将产生0.3333333333333329818。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.