Làm thế nào để thêm hai đối tượng NSNumber?


79

Bây giờ điều này phải dễ dàng, nhưng làm thế nào có thể tổng hai NSNumber? Giống như:

[one floatValue] + [two floatValue]

hay tồn tại một cách tốt hơn?

Câu trả lời:


143

Thực sự không có cách nào tốt hơn, nhưng bạn thực sự không nên làm điều này nếu bạn có thể tránh nó. NSNumbertồn tại như một trình bao bọc cho các số vô hướng để bạn có thể lưu trữ chúng trong các bộ sưu tập và chuyển chúng đa hình với các số khác NSObjects. Chúng không thực sự được sử dụng để lưu trữ các con số trong toán học thực tế. Nếu bạn thực hiện phép toán trên chúng, nó sẽ chậm hơn nhiều so với việc thực hiện thao tác chỉ trên các đại lượng vô hướng, đó có thể là lý do tại sao không có phương pháp tiện lợi nào cho nó.

Ví dụ:

NSNumber *sum = [NSNumber numberWithFloat:([one floatValue] + [two floatValue])];

Đang thực hiện tối thiểu 21 hướng dẫn về việc gửi tin nhắn, và dù có nhiều mã thì các phương pháp thực hiện để mở hộp và hộp lại các giá trị (có thể là vài trăm) để thực hiện 1 lệnh toán học.

Vì vậy, nếu bạn cần lưu trữ số dưới dạng số, hãy sử dụng dấu NSNumber, nếu bạn cần chuyển một thứ gì đó có thể là số hoặc chuỗi vào một hàm, hãy sử dụng dấu NSNumber, nhưng nếu bạn chỉ muốn làm toán với các loại C vô hướng.


1
Tôi muốn nói thêm rằng nếu bạn cần lưu trữ các bộ sưu tập số mà bạn dự định làm nhiều phép toán - có lẽ bạn thực sự muốn một mảng kiểu C có kiểu số thích hợp?
Kendall Helmstetter

Bất cứ khi nào bạn đang làm nhiều phép toán, bạn muốn sử dụng các đại lượng vô hướng, bạn muốn sử dụng các đối tượng khi bạn cần đa hình hoặc chúng cần vừa với các vùng chứa hiện có.
Louis Gerbarg

Phương thức thích hợp trên NSNumber là 'numberWithFloat:' - có lẽ điều này đã thay đổi kể từ thời điểm trả lời.
Nick vào

Bạn nói đúng, getter là floatValue, vì vậy tôi thường nhập nó ở cả hai nơi, nhưng stackoverflow không gây cho tôi lỗi biên dịch. Đã sửa
Louis Gerbarg

2
@clopez: "Bác sĩ, tôi rất đau khi làm điều này." NSNumber là một loại đóng hộp để sử dụng với các thùng chứa, không dùng cho số học. Nếu bạn đang làm số học, hãy sử dụng kiểu số học.
Stephen Canon

49

NSDecimalNumber (lớp con của NSNumber ) có tất cả các tính năng bạn đang tìm kiếm:

– decimalNumberByAdding:
– decimalNumberBySubtracting:
– decimalNumberByMultiplyingBy:
– decimalNumberByDividingBy:
– decimalNumberByRaisingToPower:

...

Nếu hiệu suất tính toán được quan tâm, thì hãy chuyển đổi sang mảng C ++ std :: vector hoặc tương tự.

Bây giờ tôi không bao giờ sử dụng C-Arrays nữa; quá dễ gặp sự cố khi sử dụng sai chỉ mục hoặc con trỏ. Và rất tẻ nhạt khi ghép mọi [] mới với xóa [].


Bạn có thể giải thích rõ hơn về ý của bạn khi "rất tẻ nhạt khi ghép mọi [] mới với xóa []." Không?
jpswain

Hãy đặt nó theo cách này. Trong c, tránh sử dụng con trỏ ở tất cả. Toàn bộ điểm của vật kính-c là đặt một lớp lên trên C mà bạn KHÔNG BAO GIỜ phải lo lắng. C không phải là ngôn ngữ được sử dụng trực tiếp. Đó là thứ cần được "quản lý" trước.
user4951

Sau khi thêm hai NSDecimalNumbers, làm thế nào để chuyển đổi NSDecimalNumberkết quả trở lại NSNumber? (Câu hỏi này là về việc thêm hai NSNumbers chứ không phải thêm hai NSDecimalNumbers.)
ohho

Tại sao bạn lại sử dụng mảng C khi bạn có một vectơ?
Jake Long

1
Tại sao bạn lại muốn chuyển đổi NSDecimalNumber thành NSNumber? Số NSDecimalNumber NSNumber:@interface NSDecimalNumber : NSNumber
Steven Fisher

12

Bạn có thể dùng

NSNumber *sum = @([first integerValue] + [second integerValue]);

Chỉnh sửa: Theo quan sát của ohho , ví dụ này là để cộng hai NSNumbertrường hợp chứa các giá trị số nguyên. Nếu bạn muốn cộng hai NSNumbercái chứa giá trị dấu phẩy động, bạn nên làm như sau:

NSNumber *sum = @([first floatValue] + [second floatValue]);

Lý do cho biểu tượng "@" là gì? Tôi không chắc mình hiểu nó làm gì trong bối cảnh này.
Mike Meyers

Ah. Bây giờ tôi thấy .... đó là chữ NSNumber, như được mô tả ở đây: stackoverflow.com/a/11120371/35723
Mike Meyers

Vâng, @mikemeyers đó là nghĩa đen mà kết thúc tốt đẹp nguyên thủy như inthoặc longhoặc đó là anh trai lớn typedef'ed NSIntegervào NSNumber đối tượng .
nemesis

integerValuecắt bớt float. Làm thế nào câu trả lời này có thể được bình chọn?
ohho

@ohho đây là một ví dụ đơn giản. Tại sao trên thế giới, bạn sẽ sử dụng integerValuenếu bạn muốn bảo toàn phần thập phân của các số?
nemesis

6

Câu trả lời được bình chọn nhiều nhất hiện nay sẽ dẫn đến các lỗi khó chẩn đoán và mất độ chính xác do sử dụng phao nổi. Nếu bạn đang thực hiện các phép toán số trên các giá trị NSNumber, trước tiên bạn nên chuyển đổi thành NSDecimalNumber và thực hiện các thao tác với các đối tượng đó.

Từ tài liệu :

NSDecimalNumber, một lớp con bất biến của NSNumber, cung cấp một trình bao bọc hướng đối tượng để thực hiện số học cơ số 10. Một cá thể có thể đại diện cho bất kỳ số nào có thể được biểu thị dưới dạng số mũ định trị x 10 ^ trong đó phần định trị là số nguyên thập phân dài tối đa 38 chữ số và số mũ là số nguyên từ –128 đến 127.

Do đó, bạn nên chuyển đổi các phiên bản NSNumber của mình thành NSDecimalNumbers bằng cách [NSNumber decimalValue]thực hiện bất kỳ số học nào bạn muốn, sau đó gán lại cho NSNumber khi bạn hoàn tất.

Trong Objective-C:

NSDecimalNumber *a = [NSDecimalNumber decimalNumberWithDecimal:one.decimalValue]
NSDecimalNumber *b = [NSDecimalNumber decimalNumberWithDecimal:two.decimalValue]
NSNumber *result = [a decimalNumberByAdding:b]

Trong Swift 3:

let a = NSDecimalNumber(decimal: one.decimalValue)
let b = NSDecimalNumber(decimal: two.decimalValue)
let result: NSNumber = a.adding(b)

0

Tại sao không sử dụng NSxEpression?

NSNumber *x = @(4.5), *y = @(-2);

NSExpression *ex = [NSExpression expressionWithFormat:@"(%@ + %@)", x, y];
NSNumber *result = [ex expressionValueWithObject:nil context:nil];

NSLog(@"%@",result); // will print out "2.5"

Bạn cũng có thể xây dựng một NSExpression có thể được sử dụng lại để đánh giá với các đối số khác nhau, như sau:

NSExpression *expr = [NSExpression expressionWithFormat: @"(X+Y)"];
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:x, @"X", y, @"Y", nil];
NSLog(@"%@", [expr expressionValueWithObject:parameters context:nil]);

Ví dụ: chúng ta có thể lặp lại đánh giá cùng một biểu thức được phân tích cú pháp, mỗi lần với một giá trị "Y" khác nhau:

 for (float f=20; f<30; f+=2.0) {
    NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:x, @"X", @(f), @"Y", nil];
    NSLog(@"%@", [expr expressionValueWithObject:parameters context:nil]);
 }

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.