値を別の表現に変換し、それを元の場所に変換するコードは悪いですが、どのように?[閉まっている]


35

私は悪いプログラミング習慣に関する記事を読んでいました。

言及した-

値を別の表現に変換してから元の位置に戻す「ヨーヨーコード」(例:小数を文字列に変換してから小数に戻す、または文字列をパディングしてからトリミングする)

彼が与えた特定の例がプログラムを書くのに悪い方法である理由を私は理解していません。値を使用できるように状況が必要な場合は、元に戻すことは問題ないようです。

誰でもこれについて説明できますか?



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?-それはどんな状況でしょうか?
コンラッド・モラウスキー14年

3
@gnatこれがいかに悪い質問になるかわかりません。必要に応じて、「値を変換して元に戻すコードは不良ですか?」と言うように編集できます。そしてそのテンプレートにはもう適合しません。
djechlin

5
最近、Javaで配列を反復処理し、JSONシリアライザーではなく文字列連結を使用して各オブジェクトをJSONオブジェクトにシリアル化するコードを見つけました。結果はプライベートメソッドに渡され、JSON配列を解析してIDの束を抽出し、IDを別の場所に渡しました。これは、システム内のそのJSON配列の唯一の使用でした。それがヨーヨーコードです。前後に変換する理由はありませんでした。元のオブジェクトからIDを渡すだけでもかまいません。
ブランドン14年

3
decimal myValue = decimal.Parse(dataReader["myColumn"].ToString())私の愛犬です。
マシュー14年

回答:


125

数値の数値表現と文字列表現の両方必要な場合でも、どちらか必要になるたびに再び変換するのではなく、一度だけ変換して元の値に固執することをお勧めします。

原則として、いつものように、存在しないコードには微妙な欠陥はありませんが、存在するコードにはしばしば存在します。それは妄想に聞こえるかもしれませんが、経験はそれが適切であることを教えてくれます。「この複雑なシステムを理解するほど頭が良くない」という永続的な軽い不安を持ってプログラミングに取り組む場合、あなたは正しい軌道に乗っています。


5
よく言った。私たちプログラマーは皆とても慎重でなければなりません。
ニール14年

58
「存在しないコードは微妙な欠陥を持つことはできませんが、存在するコードはしばしば存在します」そのために+2することができればいいのにと思います。コードを書く必要がないという価値を過小評価しないでください。
ベンジャミングリュンバウム14年

2
しかし、いくつかの単純な操作(文字列への変換と逆変換)を行うことは、ビットを操作する「正しい」方法よりもはるかに複雑ではありません(理解とコーディングが容易です)。また、特定のデータが必然的に他のフォームに変換される場合でも、カテゴリのすべてのデータを単一のフォームに保持することは良い考えです。
ダニエルRヒックス14年

36
@DanielRHicksので、その単純な日付(2014年11月10日)を文字列に変換し、-> 10-11-2014から日付に戻します->(11 oktober 2014)ちょっと待ってください。
ピーターB 14年

20
@PieterBこれはドイツ語以外のロケールのコンピューターでは機能しないドイツ語の大きな会計ソフトウェアです。最初にシステムロケールを使用して日付を文字列に変換し、次に固定ロケールで日付の解析を試み、不正な形式について文句を言います。数字やさまざまな小数点記号でも同じことを行いますが、文句を言わず、データを破壊し、奇妙な動作を示します。それを理解するのに何日もかかった。
CodesInChaos 14年

23

それは3つの大きな理由で悪いです:

  1. 変数が実際にどのようなタイプ/フォーマットであるかについては考えていないが、その時点で必要なものに変換していることを示しています。これは、設計思想の欠如を示しています。
  2. おそらく無駄です。サイクルやコード行を無駄にしている必要はほとんどありません。これにより、コードが必要以上に遅くなり、肥大化します。
  3. 型変換は微妙なエラーを起こしやすいです。コードを介してこれらの変換にドットを付けることにより、エラーの可能性が高まります。

理由1は、あなたの情報源が言及された文脈に基づいて考えていた理由だと思います。


6

説明を「元のコードと同じかそれ以上にできることをするために型を別の表現変換し、それをに戻すコード。」と言い直します。別のタイプ、それに作用し、それを元に戻すことが完全に適切であり、故障そうするには、不正な動作をもたらすであろう。

変換が良好な例として、最大1,000倍の大きさの異なる任意の符号の
4つのfloat値があり、最後の場所で0.625単位以内に合計を計算する必要があります。4つの値すべてをに変換しdouble、合計を計算し、結果をに戻すことfloatは、float単独で使用するアプローチよりもはるかに効率的です。
浮動小数点値は、せいぜい0.5ユニット(ULP)の精度です。この例では、最悪の場合の丸め誤差が、最適な最悪の場合の誤差の25%を超えないようにする必要があります。doubleを使用すると、0.5001 ULP以内の正確な値が得られます。0.625 ULP要件は不自然なように思えるかもしれませんが、そのような要件は逐次近似アルゴリズムではしばしば重要です。エラー境界がより厳密に指定されるほど、最悪の場合の反復要件は低くなります。

変換が悪い例:
浮動小数点数を持ち、その値を一意に表す文字列を出力したい場合。1つのアプローチは、数値を特定の桁数の文字列に変換し、それを元に戻して、結果が一致するかどうかを確認することです。

しかし、これは実際には貧弱なアプローチです。10進数の文字列が2つの浮動小数点値の中間点にほぼ正確に位置する値を表す場合、文字列から浮動小数点へのメソッドが常により近い値を生成することを保証するのはかなり高価ですfloat値ます。そのような保証を支持しないでください(とりわけ、数十億桁の長さであっても、ある数の数字をすべて読む必要がある場合があります)。

メソッドが、表現された値の最後の場所(ULP)で0.5625単位以内の値を常に返すことを保証する方がずっと安価です。堅牢な「可逆」10進数から文字列へのフォーマットルーチンは、出力値が正しい値からどれだけ離れているかを計算し、結果が0.25(ULP)でなければ0.375(ULP)以内になるまで数字の出力を続けます。そうしないと、一部の変換メソッドが正しく処理する文字列が出力される場合がありますが、他の変換メソッドは出力されません。

誤って解釈される可能性のある値を出力するよりも、「必要でない」数字を出力する方が良い場合があります。重要な部分は、特定のメソッドが文字列を数値に変換する試みの結果ではなく、出力プロセスに関連する数値計算に基づいて、出力する桁数を決定することです。


1
あなたの例は、OPが求めている元の値を返しません。複数の入力から計算された同じタイプの値を返すだけです。
CJデニス14年

2

様々な理由

  1. それは無意味であり、複雑さを追加します-記述および維持するコードの量、および必要なCPU時間の両方において

    1. 正確性を失うか、さらに悪いことに、値を完全に破壊する可能性があります

    2. 必要な数の表現をさらに格納すると、メモリを浪費します(言語によっては潜在的に)

受信するデータについては、可能な限り最初の最も正確な表現を保持することをお勧めします。このデータを使用して計算を実行し、出力または読みやすい形式で表示する必要がある場合にのみ変換してください。


これが作成され、前の回答で説明したもの大幅なオーバーポイントを追加していないようだ
ブヨ

2
それは投票を正当化するものですか?私は潜在的に私のポストを信じて、より簡潔な
ジョンストーリー

前の回答は、実際にそれらの両方、私にはより簡潔に見える
ブヨ

0

どうして?私たちの最高の人でさえ間違いを犯すことができるからです。

フロート<->文字列変換が安全であることを確認するために、Microsoftが「ラウンドトリップ」形式を実装しようとしたときに何が起こったのかを見てください:https : //stackoverflow.com/q/24299692/541686


0

私が学校にいたとき(そして、電気工学の放課後)、私たちは乗算後に分裂するように教えられました。除算は多くの場合、多くの桁で丸められます。除算後に乗算すると、除算エラーが乗算されます。

型変換は同じであり、データを失うリスクがあります。CInt(1.3)= 1。

私の基本言語では、型変換のみを行います(VB6プログラムは、ランタイムが行うすべてのAPI呼び出しに対してANSI / Unicode変換の時間の90%を費やします)。

型変換は、私たちが行うすべてのことを暗示しています。

 Print 5

文字列「5」は、数値リテラルから出力されます。

form1.caption = "My Form"

Unicode文字列リテラルは、ANSI文字列に変換され、フォームパッケージによってSetWindowsTextAに送信されます。

これでも基本的に機能します

a = "5"
b = 3

c = a + b (= 8)

私は最近バリアントプログラマーです。タイプについても考えていません。私は自動変換に依存しています。

とにかく私の3つのペットのふしだらな女は

変数を使用するために文字列リテラルを変数に割り当てる(メモリを浪費し、遅くなります)

コードがインラインになる可能性がある場合の無意味な関数(コンパイラはおそらく関数を取り消してインラインにします)

End Functionまたはプログラムの終了前の最後の行として、すべてのオブジェクトを何も設定しない。

短期プログラムでは4番目

5行のプログラムで3つの変数を無意味に暗くします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.