값을 다른 표현으로 변환 한 다음 시작된 위치로 다시 변환하는 코드는 어떻습니까? [닫은]


35

나는 나쁜 프로그래밍 관행에 관한 기사를 읽고 있었다 .

그것은 언급했다-

값을 다른 표현으로 변환 한 다음 다시 시작 위치로 변환하는 "요요 코드"(예 : 10 진수를 문자열로 변환 한 다음 다시 10 진수로 변환하거나 문자열을 채운 후 자르기)

그가 제공하는 특정 예가 왜 프로그램을 작성하는 나쁜 방법인지 이해할 수 없습니다. 상황에 따라 값을 사용할 수 있도록 변환하는 것이 좋습니다.

누구든지 이것에 대해 더 설명 할 수 있습니까?


4
권장 읽기 : 이 $ {블로그} 토론
모기

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 8

3
@gnat 나는 이것이 나쁜 질문이되는 방법을 얻지 못했습니다. 원하는 경우 "변환하고 값을 다시 변환하는 코드가 잘못 되었습니까?"라고 편집 할 수 있습니다. 더 이상 해당 템플릿에 맞지 않습니다.
djechlin

5
최근 Java에서 배열을 반복하여 JSON 직렬 변환기가 아닌 문자열 연결을 사용하여 각 객체를 JSON 객체로 직렬화하는 코드를 발견했습니다. 그런 다음 결과는 개인 메소드로 전달되었습니다.이 메소드는 JSON 배열을 구문 분석하여 여러 ID를 추출한 다음 ID를 다른 곳으로 전달했습니다. 이것은 시스템에서 해당 JSON 배열의 유일한 사용이었습니다. 요요 코드입니다. 변신 할 이유가 없었습니다. 우리는 단순히 원본 객체에서 ID를 전달했을 수 있습니다.
Brandon

3
decimal myValue = decimal.Parse(dataReader["myColumn"].ToString())내 애완 동물의 피브입니다.
Matthew

답변:


125

당신이 경우에도 필요가 숫자를 모두와 숫자의 문자열 표현을 대신 다시는 하나 또는 다른해야 할 때마다 변환하는, 한 번만 변환도 원래 값에 중지하는 것이 좋습니다.

원칙적으로 항상 존재하지 않는 코드는 미묘한 결함을 가질 수 없지만 종종 존재하는 코드 는 미묘한 결함을 가질 수 없습니다 . 그것은 편집증처럼 들릴지 모르지만 경험에 따르면 그것이 적절하다고 가르칩니다. "이 복잡한 시스템을 이해할만큼 똑똑하지 않다"는 영구적 인 불안감으로 프로그래밍에 접근하면 올바른 길을 가고 있습니다.


5
잘했다. 프로그래머는 모두 조심해야합니다.
Neil

58
"존재하지 않는 코드는 미묘한 결함을 가질 수 없지만, 종종 존재하는 코드는 그렇지 않습니다." 코드를 작성할 필요가없는 가치를 과소 평가하지 마십시오.
Benjamin Gruenbaum

2
그러나 비트를 조작하는 "올바른"방법보다 몇 가지 간단한 연산 (문자열로 변환 및 다시 변환)을 수행하는 것이 훨씬 덜 복잡 할 수 있습니다 (이해하기 쉽고 코딩하기가 더 쉽습니다). 특정 데이텀이 필연적으로 다른 형식으로 변환 되더라도 범주의 모든 데이터를 단일 형식으로 유지하는 것이 좋습니다.
Daniel R Hicks

36
@DanielRHicks 그래서 간단한 날짜 (2014 년 11 월 10 일)를 문자열,-> 10-11-2014로 변환하고 날짜로 다시 변환하십시오-((11 oktober 2014) 11) 안녕?
Pieter B

20
@PieterB 독일어가 아닌 로캘이있는 컴퓨터에서는 작동하지 않는 독일어 회계 소프트웨어가 있습니다. 먼저 시스템 로캘을 사용하여 날짜를 문자열로 변환 한 다음 고정 로캘로 구문 분석하고 잘못된 형식에 대해 불평합니다. 그것은 불평하지 않고 데이터를 손상시키고 이상한 행동을 나타내는 것을 제외하고는 숫자와 다양한 소수점 구분 기호와 동일합니다. 저것을 알아 내기 위해 며칠이 걸렸습니다.
코드 InChaos

23

세 가지 주요 이유로 나쁘다 :

  1. 변수가 실제로 어떤 유형 / 형식에 대해 생각하지 않았지만 대신 현재 필요한 것으로 변환하고 있음을 보여줍니다. 이것은 디자인 사고의 부족을 보여줍니다.
  2. 아마 낭비입니다. 사이클과 코드 라인을 거의 낭비하지 않고 변환 할 필요가 없습니다. 그러면 코드가 필요 이상으로 느리고 부풀어집니다.
  3. 유형 변환은 미묘한 오류가 발생하기 쉽습니다. 코드를 통해 이러한 변환을 수행하면 오류 가능성이 높아집니다.

이유 1은 소스가 언급 된 컨텍스트를 기반으로 소스가 생각한 이유라고 생각합니다.


6

나는 설명을 " 원본에서 잘 수행되었거나 더 잘 수행 될 수있는 것을 수행하기 위해 유형을 다른 표현으로 변환 한 다음 다시 변환하는 코드"로 바꾸겠다 . 다른 유형, 그것을 바탕으로 행동하고, 그것을 다시 변환하는 것은 전적으로 적절하고 있습니다 실패 잘못된 동작이 발생할 것입니다 그렇지.

변환이 좋은 예 :
하나는 float크기가 최대 1,000까지 차이가 ​​나는 4 개의 임의 부호 값을 가지며 마지막에 0.625 단위 이내로 합계를 계산해야합니다. 네 가지 값을 모두로 변환 double하고 합계를 계산 한 다음 결과를 다시 변환하는 것은 단독으로 float사용하는 방법보다 훨씬 효율적 float입니다.
부동 소수점 값은 마지막 위치 (ULP)에서 0.5 단위까지 정확합니다. 이 예에서는 최악의 반올림 오류가 최적의 최악의 오류보다 25 % 이상 높아야합니다. double을 사용하면 0.5001 ULP 내에서 정확한 값을 얻을 수 있습니다. 0.625 ULP 요구 사항이 고려 된 것처럼 보일 수 있지만 이러한 요구 사항은 연속 근사 알고리즘에서 종종 중요합니다. 에러 바운드가 더 엄격하게 지정 될수록 최악의 반복 요구 사항은 낮아집니다.

변환이 나쁜 예 :
부동 소수점 숫자가 있고 값을 고유하게 나타내는 문자열을 출력하려고합니다. 한 가지 방법은 숫자를 특정 자릿수의 문자열로 변환하고 다시 변환하여 결과가 일치하는지 확인하는 것입니다.

그러나 이것은 실제로 나쁜 접근 방식입니다. 10 진수 문자열이 두 부동 소수점 값 사이의 중간 지점에 거의 정확하게 위치하는 값을 나타내는 경우 문자열 대 부동 소수점 방법이 항상 가장 가까운 float값을 산출하도록 보장하는 것이 상당히 비싸며 , 이러한 많은 변환 방법은 '그런 보증을지지하지 마십시오 (다른 것들과 마찬가지로 어떤 경우에는 수십억 자릿수의 숫자라도 숫자의 모든 자릿수를 읽어야합니다).

메소드가 항상 표시된 값의 마지막 위치 (ULP)에서 0.5625 단위 내에있는 값을 리턴하도록 보장하는 것이 훨씬 저렴합니다. 강력한 "가역"10 진수 문자열 형식화 루틴은 출력 값이 올바른 값에서 얼마나 떨어져 있는지 계산하고 0.25 (ULP)가 아닌 경우 결과가 0.375 (ULP) 내에 올 때까지 숫자를 계속 출력해야합니다. 그렇지 않으면 일부 변환 방법이 올바르게 처리하는 문자열이 출력 될 수 있지만 다른 변환 방법은 그렇지 않습니다.

잘못 해석 될 수있는 값을 출력하는 것보다 "필요하지 않은"숫자를 출력하는 것이 더 좋습니다. 중요한 부분은 문자열을 다시 숫자로 변환하려는 특정 방법의 시도 결과가 아니라 출력 프로세스와 관련된 숫자 계산을 기반으로 얼마나 많은 자릿수를 출력해야하는지 결정해야한다는 것입니다.


1
귀하의 예는 OP가 요구하는 원래 값을 반환하지 않습니다. 여러 입력에서 계산 된 동일한 유형의 값만 반환합니다.
CJ Dennis

2

여러가지 이유

  1. 무의미하고 작성 및 유지해야 할 코드의 양과 필요한 CPU 시간이 모두 복잡해집니다.

    1. 정확도가 떨어지거나 악화 될 수 있습니다.

    2. 필요한 숫자의 더 많은 표현을 저장하면 (언어에 따라 잠재적으로) 메모리를 낭비합니다.

모범 사례는 수신 한 모든 데이터에 대해 가장 정확한 첫 번째 표현을 유지하는 것입니다. 이 데이터를 사용하여 계산을 수행하고, 출력하거나 읽기 쉬운 형식으로 표시해야하는 경우에만 변환하십시오.


이것은 이전 답변에서 만들어지고 설명 된 점들에 비해 실질적인 것을 추가하지 않는 것 같습니다
gnat

2
투표가 정당화됩니까? 내 게시물이 더 간결하게 믿습니다
Jon Story

이전 답변은 실제로 나에게 더 간결 해 보입니다.
gnat

0

왜? 우리 중 최고조차도 실수를 할 수 있기 때문입니다.

float <-> 문자열 변환이 안전한지 확인하기 위해 Microsoft가 "왕복"형식을 구현하려고 할 때 어떤 일이 발생했는지 살펴보십시오. https://stackoverflow.com/q/24299692/541686


0

내가 학교에있을 때 (그리고 전기 공학의 포스트 스쿨) 우리는 곱한 후에 나누는 법을 배웠다. 나눗셈은 종종 많은 숫자로 반올림됩니다. 나누기 후 곱하기 나누기 오류가 곱해집니다.

유형 변환은 동일하므로 데이터가 손실 될 위험이 있습니다. CInt (1.3) = 1.

내 언어 인 Basic에서는 유형 변환 만 수행합니다 (VB6 프로그램은 런타임의 모든 API 호출에 대해 ANSI / 유니 코드 변환에 90 %의 시간을 소비합니다).

타입 변환은 우리가하는 모든 것을 암시합니다.

 Print 5

문자열 "5"는 숫자 리터럴에서 인쇄됩니다.

form1.caption = "My Form"

유니 코드 문자열 리터럴은 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.