0.0和1.0是否被视为幻数?

时间:2013-10-22 15:04:58

标签: java coding-style floating-point magic-numbers

我知道-1012是幻数规则的例外。但是我想知道它们是浮子时是否也是如此。我是否必须为它们初始化最终变量,或者我可以直接在我的程序中使用它们。

我在课堂上使用它作为百分比。如果输入小于0.0或大于1.0,那么我希望它将百分比自动设置为零。因此,如果(0.0 <=输入&amp;&amp;输入&lt; = 1.0)。

谢谢

4 个答案:

答案 0 :(得分:2)

这实际上取决于背景。避免幻数的重点是保持代码的可读性。使用您的最佳判断,或向我们提供一些背景信息,以便我们可以使用我们的。

幻数是[u]nique values with unexplained meaning or multiple occurrences which could (preferably) be replaced with named constants

http://en.wikipedia.org/wiki/Magic_number_(programming)

编辑:何时记录带有变量名称的代码与何时只使用数字是一个备受争议的话题。我的观点是上面链接的Wiki文章的作者:如果你的代码中的含义不是很明显且多次出现,请使用命名常量。如果它只出现一次,只需注释代码。

如果您对其他人(强烈偏见)的意见感兴趣,请阅读 What is self-documenting code and can it replace well documented code?

答案 1 :(得分:2)

这些数字并不是幻数规则的真正例外。常识规则(就“一个”规则而言),当它没有简化到教条的水平时,基本上是“不要在不能使其意义明显的语境中使用数字”。事实恰恰相反,这四个数字在明显的背景下非常常用。这并不意味着它们是唯一适用的数字,例如:如果我有:

long kilometersToMeters(int km) { return km * 1000L; }

命名数字确实没有意义:从微小的背景来看,很明显它是一个转换因子。另一方面,如果我在一些低级代码中执行此操作:

sendCommandToDevice(1);

它仍然是错误的,因为它应该是一个常数kResetCommand = 1或类似的东西。

因此0.01.0是否应该被常量替换完全取决于上下文。

答案 2 :(得分:0)

通常,每个规则都有例外(也是这个例子)。对这些常量使用一些助记符名称是一种风格问题。

例如:

int Rows = 2;
int Cols = 2;

是一个非常有效的例子,原始值的使用会产生误导。

神奇数字的含义应该从上下文中显而易见。如果不是 - 给这个东西起个名字。

答案 3 :(得分:0)

为某物添加名称会创建一个身份。鉴于定义

const double Moe = 2.0;
const double Joe = 2.0;
...
double Larry = Moe;
double Harry = Moe;
double Garry = Joe;

使用Moe和Joe的符号表明Larry和Harry的默认值彼此相关,其方式是Garry的默认值不是。是否定义特定常量的名称的决定不应该取决于该常量的值,而是取决于它是否会巧合地出现在代码中的多个位置。如果一个人正在与一个远程设备通信,该设备要求向其发送特定的字节值以触发重置,我会考虑:

void ResetDevice()
{
  // The 0xF9 command is described in the REMOTE_RESET section of the
  // Frobnitz 9000 manual
  transmitByte(0xF9);
}
... elsewhere
myDevice.ResetDevice();
...
otherDevice.ResetDevice();

在许多情况下优于

// The 0xF9 command is described in the REMOTE_RESET section of the
// Frobnitz 9000 manual
const int FrobnitzResetCode = 0xF9;
... elsewhere
myDevice.transmitByte(FrobnitzResetCode );
...
otherDevice.transmitByte(FrobnitzResetCode );

在重置Frobnitz 9000设备的上下文之外,值0xF9没有实际意义。除非有一些理由为什么外部代码本身应该更喜欢发送必要的值而不是调用ResetDevice方法,否则该常量应该对该方法之外的任何代码没有任何价值。虽然可以使用

void ResetDevice()
{
  // The 0xF9 command is described in the REMOTE_RESET section of the
  // Frobnitz 9000 manual
  int FrobnitzResetCode = 0xF9;
  transmitByte(FrobnitzResetCode);
}

对于在如此狭隘的背景下定义某个名称的确没有多大意义。

关于像0和1这样的值的唯一“特殊”是比其他常量更常使用,例如23如果他们在使用它们的上下文之外没有特定于域的身份。如果一个人使用的函数要求第一个参数表示附加参数的数量(在C中有点常见),最好说:

output_multiple_strings(4, "Bob", Joe, Larry, "Fred"); // There are 4 arguments
...
output_multiple_strings(4, "George", Fred, "James", Lucy);  // There are 4 arguments

比     #define NUMBER_OF_STRINGS 4 //有4个参数

output_multiple_strings(NUMBER_OF_STRINGS, "Bob", Joe, Larry, "Fred");
...
output_multiple_strings(NUMBER_OF_STRINGS, "George", Fred, "James", Lucy);

后一种语句意味着传递给第一种方法的值与传递给第二种方法的值之间的连接比传递给第一种方法的值与该方法调用中的任何其他值之间的连接更强。除其他事项外,如果需要更改其中一个调用以传递5个参数,则在第二个代码示例中将不清楚应该更改哪些以允许它。相反,在前一个样本中,常数“4”应改为“5”。