如何获得Float的长度? (C#)

时间:2014-06-30 01:18:02

标签: c#

我从C#计算机编程基础学习C#'由Svetlin Nakov和其他人(在这里免费提供:http://www.introprogramming.info/english-intro-csharp-book/

每章后,作者都喜欢提出超出本章范围的问题。第135页,问题3要求我编写一个能够正确比较两个实数的程序,准确度为0.000001(7位有效数字)。

所以我使用浮点数来比较数字,我决定添加一些代码,检查输入的数字是否超过浮点数可以处理的7位有效数字。所以我需要检查有效位数。谷歌告诉我,我应该使用sizeof(float)来做到这一点,但是我在sizeof check的行上不断出现CS0246错误(找不到类型或名称空间。)

如果我不包含检查数字长度的代码,该程序是有效的。我无法在C#上找到SO的答案。

问题是什么?

编辑:感谢您的所有答案。让我澄清一下我的问题:我理解解析字符串浮动会自动检查有效性。但是,我昨天尝试了我的程序,浮动将失去超过7位有效数字。因此,如果我比较0.123457和0.12345678,程序将声明这两个数字是相同的,因为第二个数字是向上舍入的。这就是我试图捕获超过7位数的浮点数的原因。我以这种方式解释这个问题,因为我发现这两个非常相似但不相同的数字在裂缝中滑落。

using System;

// Compare two real numbers with up to 0.000001 (7) significant digits
class Compare_Numbers
{
static void Main(string[] args)
{
    // Processing the first number
    String firstNumString = null;
    Console.WriteLine("This program compares 2 numbers with upto 7 significant digits.\nEnter the FIRST number with up to 7 significant digits");
    firstNumString = Console.ReadLine();
    float firstNum = Single.Parse(firstNumString);

    if (sizeof(firstNum) > 7)
    {
        Console.WriteLine("That number is too long!\nEnter a number with a MAX of 7 significant digits!");
    }

    // Processing the second number
    String secondNumString = null;
    Console.WriteLine("Enter the SECOND number with up to 7 significant digits");
    secondNumString = Console.ReadLine();
    float secondNum = Single.Parse(secondNumString);

    if (sizeof(secondNum) > 7)
    {
        Console.WriteLine("That number is too long!\nEnter a number with a MAX of 7 significant digits!");
    }

    if (firstNum == secondNum)
    {
        Console.WriteLine("The two numbers are the SAME!");
    }
    else
    {
        Console.WriteLine("The two numbers are DIFFERENT!");
    }
}

}

3 个答案:

答案 0 :(得分:2)

" 如何获得Float的长度? "

简而言之,假设7位有效数字:

  firstNum.ToString("G7").Length // 7 significant digits

实施例。

  float pi = 3.14159265f;
  string g5 = a.ToString("G5");
  string g7 = a.ToString("G7");

然而,你的标题要求一些简单的东西,但你的问题正文表明了别的东西。因此,您似乎认为找到浮点数的长度是为了获得更大的解决方案。我不确定,所以我只想指出几个问题。

首先,您滥用 sizeof ; C#中的 sizeof ()采用的是类型,而不是变量。 (因此sizeof(float)可以工作,但 sizeof (num))。

在任何情况下, sizeof 它都不会为您提供有效位数。它将为您提供非托管类型存储的字节数,它将是常量(4,8等)。相反,对于给定的字符串,请使用 String.Length

但是,无法做的是尝试将数字解析为浮点数,然后通过检查浮点变量来尝试检查超出范围的值。根据定义,如果您可以成功解析浮点数,那么它是有效的。如果它无效,则无法解析。您使用Single.Parse()然后继续尝试使用float变量进行验证的示例部分是没有实际意义的。您需要验证字符串值,或验证解析是否成功,或者更改您的方法。

我认为最简单的解决方案是使用Single.TryParse()并检查布尔返回值。如果返回false,则字符串值无效,或者超出Single.MinValue和Single.MaxValue的范围。因此,您可能会重新考虑您的方法(因为它不是作者的原始挑战)。我个人会在我的计算器中使用C#中的大型类型,但练习的目的可能是学习这些切向问题,所以:

  1. 如果您已经有一个精度(浮点数),那么您可以通过使用Single.ToString()或string.Format()并使用 string.Length 在结果上,虽然它将包括小数点,所以说明这一点。

    请参阅:

    中的ToString()和格式说明符

    http://msdn.microsoft.com/en-us/library/fzeeb5cd(v=vs.110).aspx

    http://msdn.microsoft.com/en-us/library/0c899ak8(v=vs.110).aspx

    这个问题是当你使用ToString()时你已经有了一个有效的浮点数,到那时检查是没有意义的。您需要检查原始值。见(2)

  2. 如果你是从一个字符串开始的(在这个例子中,你是从控制台读到字符串,然后用Single.Parse()解析,那么你将获得一个有效值或一个例外。你需要使用带有Single.Parse()的try-catch块,否则切换到Single.TryParse()并检查布尔返回值。

  3. 最后,如果您想确保既可以解析值,又可以验证更高精度或范围的数字,也可以添加Double.TryParse()。

    if(!Single.TryParse(str, ref snum)) {
       if(Double.TryParse(str, ref dnum))
           // valid number is out of range for Single
       else
           // valid number is out of range for Double, or invalid
    }
    

    或者你可以使用Single.Parse和catch(OverflowException)

    try {
        snum = Single.Parse(str);
    }
    catch(OverflowException e) {
    }
    

    关于你的实际问题所说的一切,但问题的精神是如何比较2个有效数字,在我看来。在这种情况下,使用TryParse()来验证它们,然后直接比较它们,或者使用@ drf的回答https://stackoverflow.com/a/24482343/257090

    中给出的方法

答案 1 :(得分:1)

  static private int GetNumDigitsInFloat(float n)
  {
     string s = n.ToString();
     return s.Length - 1;
  }

答案 2 :(得分:0)

如果目的是确保两个浮点数在1E-7内大致相等,则根本不需要转换为字符串。实际上,使用字符串转换可能不是一种强大的方法:

  • 所写的问题需要小数点后的七个有效数字,而不是七个有效数字。字符串的长度将包括两者。
  • 默认情况下,
  • Single.ToString仅打印7位精度,但内部最多可存储9位数。浮动20.000001和20.000003默认都会转换为“20”,但在1e-7内不相等。 (这是字符串转换的函数,而不是此数据类型的精度限制。)
  • 可以解析浮点数并以指数表示法输出。如果用户在提示符处输入1e+20,这是一个长度为5的完全有效的浮点数,会发生什么?

鉴于两个数字f1f2以及10 ^ -7的接受错误ε,数学上遵循f1f2应该是当且仅在以下情况下被认为是平等的(在可接受的容忍范围内):

 |f1 - f2| ≤ ε

或者在C#中,我们可以编写等效函数:

// preconditions: e is non-negativeps, f1 and f2 are not NaN, Inf, or -Inf.
bool AreApproximatelyEqual(float f1, float f2, float eps)
{
    return Math.Abs(f1 - f2) <= eps;
}

给定浮点firstNumsecondNum,得到近似相等:

bool equal = AreApproximatelyEqual(firstNum, secondNum, 1e-7f);