문제

나는 nsdecimal, nsnumber, nsnumberdecimal, cfnumber에 대해 많은 것을 읽었습니다 ... 그리고 그것은 나에게 일종의 정글이되기 시작합니다.

기본적으로 나는 이와 같은 간단한 계산을 처리 할 간단한 모델 클래스를 만들려고 노력하고 있습니다.

#import <Foundation/Foundation.h>


@interface Test : NSObject
{
    float rate;
    float amount;
    int duration;
}

- (float)capitalizedAmount;

@end

@implementation Test

- (float)capitalizedAmount {
    return (amount*pow((1.0+rate),duration));
}

@end

나는이 방법과 세트를 문자열로 사용 하여이 방법과 세터에 액세스하고 싶습니다. 왜냐하면이 클래스와 같은 다른 클래스를 많이 가질 계획이므로 주요 가치 코딩을 수행 할 필드 목록 만 보관하고 있습니다.

// This is just the desired behavior
// This evidently won't work with the previous class definition
Test *obj = [[Test alloc] init];
[NSNumber numberWithInt:10]
...
float r;
r = [obj performSelector:NSSelectorFromString(@"capitalizedAmount")];

나는 이것이 불가능하다는 것을 이해합니다 performSelector: 물체를 반환 할 것입니다 capitalizedAmount 물체를 반환해야합니다. 나는 내용을 읽었습니다 NSInvocation 그리고 comp.lang의 대상 C FAQ의 관련 부분.

나는 또한 내가 사용해야한다는 것을 이해합니다 NSDecimalNumber, 그러나 알고 싶은 두 가지가 있습니다.

  1. 메모리 오버 헤드와 성능 손실은 다소 복잡한 클래스 (이런 종류의 재무 계산 만, uitable view에서 보여 지)에 허용됩니까? 나는 C에 대한 배경이별로 없다.
  2. 기능을 사용하기에는 너무 까다 롭고 복잡하지 않습니까? decimalNumberByAdding:? 파이썬을 사용하면 정의하기가 쉽습니다 __add__ 객체와 함께 연산자를 사용합니다. 플로트 값을 얻을 수 있어야합니다 NSDecimalNumber, 그런 다음 계산을 수행하고 결과를 NSDecimalNumber? 이 문제를 어떻게 처리 하시겠습니까?

나는 단순하고 아름다운 솔루션을 찾고 있습니다!

같은 영역에있는 또 다른 질문은 다음과 같습니다 CFBoolean 객체 래퍼 BOOL iPhone Core Foundation에서?

당신의 도움을 주셔서 대단히 감사합니다!

도움이 되었습니까?

해결책

재무 계산을 다루는 경우 표준 Base-2 플로팅 포인트 유형에서 발생할 수있는 반올림 오류를 피하기 위해 Base-10 산술을 사용해야합니다. 따라서 NSDECIMAL 또는 NSDECIMALNUMBER입니다. 객체 지향 코드를 작성하기 때문에 NSDECIMALNUMBER가 귀하에게 적합한 선택입니다.

질문에 답하기 위해 : 코드의 테스트 만 메모리 오버 헤드와 성능 손실이 허용되는지 여부를 밝힐 수 있습니다. 나는 NSDECIMALNUMBER와 실제로 많은 일을하지 않았지만 Apple의 구현이 매우 효율적이며 대부분의 사람들의 요구에 적합 할 것이라고 베팅 할 것입니다.

불행히도, 당신은 decimalNumberByAdding: Objective-C는 C ++처럼 연산자 과부하를 지원하지 않기 때문입니다. 나는 그것이 당신의 코드를 다소 우아하게 만든다는 데 동의합니다.

게시 한 코드에 대한 댓글 하나 : r = [obj performSelector:NSSelectorFromString(@"capitalizedAmount")]; 다소 불가사의합니다. 어느 하나

r = [obj performSelector:@selector(capitalizedAmount)];

또는 심지어 단순한

r = [obj capitalizedAmount];

필요하지 않으면 더 좋을 것입니다 NSSelectorFromString 다른 이유에 대한 구문.

다른 팁

OLE은 맞습니다. 재무 계산을 수행 할 때 부동 소수점 수학 오류를 피하기 위해 NSDECIMAL 또는 NSDECIMALNUMBER를 사용해야합니다. 그러나 내 제안은 nsdecimalnumber가 아닌 nsdecimal과 그 C 함수를 사용하는 것입니다. nsdecimal 계산이 훨씬 빠를 수 있으며, 많은 자동 퇴행 객체를 생성하지 않기 때문에 메모리 사용에있어 훨씬 좋습니다.

예를 들어, 나는 MacBook Air의 두 유형에 대한 수학 작업을 벤치마킹했습니다.

NSDecimal

Additions per second: 3355476.75
Subtractions per second: 3866671.27
Multiplications per second: 3458770.51
Divisions per second: 276242.32

NSDecimalNumber

Additions per second: 676901.32
Subtractions per second: 671474.6
Multiplications per second: 720310.63
Divisions per second: 190249.33

NSDECIMAL 대 NSDECIMALNUMBER를 사용할 때 성능이 약 5 배 증가하지 않은 유일한 작업이었습니다. iPhone에서도 비슷한 성능 향상이 발생합니다. 이것은 메모리 절약과 함께 최근 코어 플롯을 NSDECIMAL 사용으로 전환 한 이유였습니다.

당신이 달라질 수있는 유일한 어려움은 nsdecimal 유형으로 안팎으로 값을 얻는 것입니다. 플로트 및 정수 값으로 직접오고 나가면 NSDECIMALNUMBER를 브리지로 사용해야 할 수도 있습니다. 또한 핵심 데이터를 사용하는 경우 NSDECIMALS가 아닌 NSDECIMALNUMBERS로 값을 저장하게됩니다.

나는이 방법과 세트를 문자열로 사용 하여이 방법과 세터에 액세스하고 싶습니다. 왜냐하면이 클래스와 같은 다른 클래스를 많이 가질 계획이므로 주요 가치 코딩을 수행 할 필드 목록 만 보관하고 있습니다.

r = [obj performSelector:NSSelectorFromString(@"capitalizedAmount")];

KVC는 단순히 문자열을 사용하여 객체에 메시지를 보내는 것이 아닙니다. 보다 키 값 코딩 프로그래밍 안내서.

nsdecimalNumber에서 float 값을 얻은 다음 계산을 수행하고 nsdecimalNumber로 래핑 한 결과를 반환해야합니까?

아니요. 바이너리 플로팅 지점으로의 전환 (float/double) 소수점 부동 소수점에서 (NSDecimal/nsdecimalNumber)는 손실입니다. 그런 식으로 수행하면 일부 계산에 대한 결과가 잘못됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top