将值转换为不同表示形式,然后再将其转换回其起始位置的代码很不好,但是如何?[关闭]


35

我正在阅读一篇有关不良编程习惯文章

它提到-

“ Yo-Yo代码”将值转换为不同的表示形式,然后将其转换回其起始位置(例如:将十进制转换为字符串,然后转换为十进制,或者填充字符串然后对其进行修整)

我不明白为什么他给出的特定示例对编写程序来说是一种不好的方式。如果情况需要,我可以将其转换回去,以便可以使用该值。

有人可以解释更多吗?


4
推荐阅读:讨论此$ {blog}
2014年

8
在大多数情况下,它只是多余的,它的发生仅仅是因为程序员不知道获得他们想要的东西的更好的方法。博客条目在以下几段中提供了一个典型示例:"Roundabout code" that accomplishes in many instructions what could be done with far fewer (eg: rounding a number by converting a decimal into a formatted string, then converting the string back into a decimal)if the situation is so that they have to be used?-那会是什么情况?
Konrad Morawski

3
@gnat我不知道这怎么使这成为一个坏问题。如果需要,我可以将其编辑为“代码转换后的值变坏了吗?” 并且它不再适合该模板。
djechlin

5
我最近在Java中找到了在数组上迭代的代码,使用字符串连接而不是JSON序列化器将每个对象序列化为JSON对象。然后将结果传递给私有方法,该方法解析JSON数组以提取一堆ID,然后将ID传递到其他地方。这是系统中该JSON数组的唯一用法。那是悠悠球代码。没有理由来回转换。我们可以简单地从原始对象传递ID。
布兰登

3
decimal myValue = decimal.Parse(dataReader["myColumn"].ToString())是我的宠儿。
马修

Answers:


125

即使确实需要数字的数字表示形式和字符串表示形式,也最好只转换一次并保留原始值,而不是每次都需要转换时再转换一次。

原则是,一如既往,不存在的代码不能具有细微的缺陷,而经常存在的代码却可以具有细微的缺陷。听起来可能有些偏执,但是经验告诉我们这是适当的。如果您对编程的永久性焦虑是“我不够聪明,无法理解这个复杂的系统”,那么您的方向正确。


5
说得好。我们程序员都应该非常谨慎。
尼尔

58
“不存在的代码不能具有细微的缺陷,而经常存在的代码却可以。”希望我能为此加2。永远不要低估不必编写代码的价值。
本杰明·格林鲍姆

2
但是,进行一些简单的操作(转换为字符串并返回)可能比“正确”的操作位方式复杂得多(更易于理解和编码)。即使将某个基准不可避免地转换为其他形式,将一个类别的所有数据都保持为单一形式通常也是一个好主意。
Daniel R Hicks 2014年

36
@DanielRHicks,让我们将简单的日期(2014年11月10日)转换为字符串-> 10-11-2014并返回日期->(2014年10月11日)嘿,等等?
Pieter B

20
@PieterB有一个很大的德语会计软件,因为它会在非德语语言环境的计算机上不起作用。它首先使用系统区域设置将日期转换为字符串,然后尝试使用固定的区域设置解析日期,并抱怨非法格式。它与数字和变化的小数点分隔符的作用相同,除了它在那里不抱怨,破坏数据并表现出奇怪的行为。花了我几天的时间弄清楚那个。
CodesInChaos

23

不好的原因有三个:

  1. 它表明您尚未考虑变量实际上应该是哪种类型/格式,而是在那时将其转换为所需的内容。这表明缺乏设计思想。
  2. 这可能很浪费。几乎可以肯定,您正在浪费周期和代码行,进行了不必要的转换。这将使您的代码比所需的速度更慢,更膨胀。
  3. 类型转换容易产生细微的错误。通过在代码中添加这些转换,您增加了出错的可能性。

我怀疑原因1是您的消息来源根据提到的上下文考虑的原因。


6

我将描述改写为“代码,该代码将类型转换为其他表示形式,目的是执行原本可以做得更好或更好的事情,然后再将其转换回去。在很多情况下,将某物转换为一个不同类型,作用于它,并将其转换回是完全适当的,未能这样做将导致不正确的行为。

举例来说,转换效果很好:
其中一个具有四个float任意符号值,其大小可能相差最大1,000倍,并且最后一个位置需要计算总和至0.625单位之内。将所有四个值转换为double,计算总和并将结果转换回float会比float单独使用任何一种方法更有效。
浮点值最多精确到最后一位(ULP)0.5个单位。此示例将要求最坏情况下的舍入误差比最佳最坏情况下的误差高出不超过25%。使用双精度会产生一个在0.5001 ULP之内准确的值。虽然看起来像是0.625 ULP要求,但在逐次逼近算法中,此类要求通常很重要。指定的误差范围越严格,最坏情况下的迭代要求就越低。

举一个转换不好的例子:
一个有一个浮点数,并希望输出一个唯一表示其值的字符串。一种方法是将数字转换为具有一定位数的字符串,尝试将其转换回原位,然后查看结果是否匹配。

但这实际上是一种糟糕的方法。如果十进制字符串表示的值几乎恰好位于两个浮点值之间的中间点,则字符串到浮点方法要保证总是产生更接近的值,这是相当昂贵的float,许多此类转换方法都不会不能坚持这样的保证(除其他外,在某些情况下,这样做需要读取数字的所有数字,即使长度为数十亿个数字也是如此)。

对于一种方法来说,保证它始终返回所表示值的最后一位(ULP)内0.5625单位内的值,这是便宜得多的。健壮的“可逆”十进制字符串格式例程应计算输出值与正确值的距离,并继续输出数字,直到结果在0.375(ULP)内(如果不是0.25(ULP))。否则,它可能会输出一个字符串,某些转换方法可以正确处理该字符串,而其他转换方法则不能。

有时输出一个不是“必需”的数字比输出一个可能被误解的值更好。关键部分在于,应基于与输出过程相关的数值计算来决定应输出多少位数字,而不是基于一种将字符串转换回数字的特定方法的尝试结果。


1
您的示例未返回OP询问的原始值。它仅返回由多个输入计算得出的相同类型的值。
CJ丹尼斯2014年

2

很多原因

  1. 它毫无意义,而且增加了复杂性-既要编写和维护的代码量,又需要CPU时间

    1. 可能会失去准确性甚至更糟,完全破坏价值

    2. 当您最终存储所需数字的更多表示形式时,这会浪费内存(可能取决于语言)

一个好的做法是,对于收到的任何数据,都尽可能保留最准确的首个表示。使用此数据执行任何计算,并且仅在需要输出或以易于阅读的格式显示时才进行转换。


这似乎并没有为先前的回答中提出和解释的观点增加任何实质性内容
咬2014年

2
这是否证明了投反对票?我相信我的帖子可能更简洁
乔恩故事

之前的答案实际上看起来更简洁给我,他们都
蚊蚋


0

当我在学校(和电气工程的研究生院)时,我们被教成乘法后的除法。除法经常是很多位数,并且会四舍五入。除法后相乘将除法误差乘以。

类型转换是相同的,您可能会丢失数据。CInt(1.3)= 1。

用我的语言Basic,我们只进行类型转换(对于运行时进行的所有API调用,VB6程序花费90%的时间进行ANSI / Unicode转换)。

我们所做的一切都暗示了类型转换。

 Print 5

从数字文字中打印字符串“ 5”。

form1.caption = "My Form"

unicode字符串文字被转换为ANSI字符串,并通过表单包发送到SetWindowsTextA。

即使这基本

a = "5"
b = 3

c = a + b (= 8)

这些天我是一名变体程序员-我什至不考虑类型。我只是依靠自动转换。

反正我的三只宠物都是

将字符串文字分配给变量以使用它们(浪费内存并降低速度)

代码可以内联时的无意义函数(编译器可能会撤消函数并以内联方式对其进行内联)

将所有对象设置为无,作为End Function或程序结束之前的最后几行。

短节目第四名

在5行程序中无意义地将3个变量变暗。

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.