2009-07-24 21 views
6

? Estoy confundido por NSDecimalNumber y sus "comportamientos". Tengo un NSDecimalNumber que representa un valor en dólares, digamos $ 37.50. Me gustaría saber cuántas veces digamos 5.0 en ese número y luego saber qué sobra. Puedo obtener la división recta y obtener 7.50 pero quiero 7 mod 2.50. Podría convertir a un número entero pero necesito guardar los "centavos" para preguntarme si hay algunos trucos en el marco.¿Cómo se obtiene el int y el módulo (mod) de la división con un NSDecimalNumber

Respuesta

1

En teoría, podría hacer algunos trucos con los métodos NSDecimalNumber decimalNumberByDividingBy:, decimalNumberByMultiplyingBy: y decimalValue. Divida los números, tome la estructura decimal, calcule el resto de la estructura, luego cree un nuevo número decimal con ese resto y multiplique el resto por el número original.

La manera más fácil de hacerlo, sin embargo, sería averiguar la precisión máxima que desea (llámala N lugares después del punto decimal), multiplique el número por 10eN, luego simplemente tome el valor entero y haga su división y mod sobre eso. Sin embargo, corres el riesgo de perder datos, especialmente con números muy grandes, así que verifica el número más grande que desees y averigua qué tipo de datos, si hay alguno, funcionará para ti. NSNumber no es compatible con unsignedLongLongValue.

4
  1. Divida el dividendo por el divisor, redondeando hacia abajo. Esto te da el cociente.
  2. Multiplica el divisor por el cociente.
  3. Reste eso del dividendo. Esto te da el resto.

(37.50 // 5) == 7; 7 * 5 == 35; 37.50 - 35 = 2.50.

(Nota:... // es operador de Python para la división integrante He prestado aquí Obviamente, se debe en realidad no intenta utilizar // para la división en código Objective-C)

+0

Para redondear, use floor() de math.h - toma un doble y devuelve un doble. –

+0

Si usa números decimales, intente permanecer dentro de ese tipo tanto como sea posible. A saber, para redondear use decimalNumberByRoundingAccordingToBehavior :. – Tim

+0

Mejor aún, use 'decimalNumberByDividingBy: withBehavior:' para hacer la división. Entonces no necesitas redondear por separado. –

6

Usando ejemplo Peter Hoseys, pero con código de iOS:

NSDecimalNumber *dividend = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithDouble:37.5] decimalValue]]; 

NSDecimalNumber *divisor = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithDouble:5.0] decimalValue]]; 

NSDecimalNumber *quotient = [dividend decimalNumberByDividingBy:divisor withBehavior:[NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:0 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]]; 

NSDecimalNumber *subtractAmount = [quotient decimalNumberByMultiplyingBy:divisor]; 

NSDecimalNumber *remainder = [dividend decimalNumberBySubtracting:subtractAmount]; 
+0

Tiene que establecer el modo de redondeo a la derecha si uno de dividendo o divisor es negativo. 'NSRoundingMode roundingMode = ((dividend.floatValue <0)^(divisor.floatValue <0))? NSRoundUp: NSRoundDown; ' – user500

5

Aquí es una categoría NSDecimalNumber que también trabaja con números negativos y divisores negativos:

- (BOOL)isNegative 
{ 
    return (NSOrderedDescending == [[NSDecimalNumber zero] compare:self]); 
} 

- (NSDecimalNumber *)invertedNumber 
{ 
    NSDecimalNumber *negOne = [NSDecimalNumber decimalNumberWithMantissa:1 exponent:0 isNegative:YES]; 
    return [self decimalNumberByMultiplyingBy:negOne]; 
} 

- (NSDecimalNumber *)moduloFor:(NSDecimalNumber *)divisor 
{ 
    NSRoundingMode roundingMode = ([self isNegative]^[divisor isNegative]) ? NSRoundUp : NSRoundDown; 
    NSDecimalNumberHandler *rounding = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:roundingMode 
                           scale:0 
                        raiseOnExactness:NO 
                        raiseOnOverflow:NO 
                        raiseOnUnderflow:NO 
                       raiseOnDivideByZero:NO]; 

    // divide and get the remainder 
    NSDecimalNumber *quotient = [self decimalNumberByDividingBy:divisor withBehavior:rounding]; 
    NSDecimalNumber *subtract = [quotient decimalNumberByMultiplyingBy:divisor]; 

    NSDecimalNumber *modulo = [self decimalNumberBySubtracting:subtract]; 
    if ([divisor isNegative]) { 
     return [modulo invertedNumber]; 
    } 
    return modulo; 
} 
Cuestiones relacionadas