我从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!");
}
}
}
答案 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#中的大型类型,但练习的目的可能是学习这些切向问题,所以:
如果您已经有一个精度(浮点数),那么您可以通过使用Single.ToString()或string.Format()并使用 string.Length 转换为字符串来获取长度strong>在结果上,虽然它将包括小数点,所以说明这一点。
请参阅:
中的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)
如果你是从一个字符串开始的(在这个例子中,你是从控制台读到字符串,然后用Single.Parse()解析,那么你将获得一个有效值或一个例外。你需要使用带有Single.Parse()的try-catch块,否则切换到Single.TryParse()并检查布尔返回值。
最后,如果您想确保既可以解析值,又可以验证更高精度或范围的数字,也可以添加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的完全有效的浮点数,会发生什么?鉴于两个数字f1
和f2
以及10 ^ -7的接受错误ε
,数学上遵循f1
和f2
应该是当且仅在以下情况下被认为是平等的(在可接受的容忍范围内):
|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;
}
给定浮点firstNum
和secondNum
,得到近似相等:
bool equal = AreApproximatelyEqual(firstNum, secondNum, 1e-7f);