Cách tăng số NSN


108

Làm cách nào để tăng số NSN?

tức là myNSNumber ++


2
Hãy nhớ rằng: khi sử dụng NSNumber *, hãy luôn kiểm tra xem các kiểu nguyên thủy có đủ hay không.
WKS

1
Tôi ngạc nhiên rằng không có câu trả lời nào cung cấp cách nhanh chóng / tối ưu hóa để làm điều đó, bởi vì chỉ để tăng giá trị, bạn cần truy vấn, kết hợp và tạo đối tượng mới, do đó, thực hiện điều này trong vòng lặp có thể trở nên tốn thời gian.
PetrV

Câu trả lời:


123

Cập nhật: FYI, cá nhân tôi thích câu trả lời một dòng của BoltClock và DarkDusts hơn. Chúng ngắn gọn hơn và không yêu cầu các biến bổ sung.


Để tăng một NSNumber, bạn sẽ phải lấy giá trị của nó, tăng giá trị đó và lưu trữ nó trong một giá trị mới NSNumber.

Ví dụ, đối với NSNumbermột số nguyên đang giữ:

NSNumber *number = [NSNumber numberWithInt:...];
int value = [number intValue];
number = [NSNumber numberWithInt:value + 1];

Hoặc để NSNumbergiữ một số dấu phẩy động:

NSNumber *number = [NSNumber numberWithDouble:...];
double value = [number doubleValue];
number = [NSNumber numberWithDouble:value + 1.0];

62
Đây là lý do số một khiến tôi ghét thuộc tính NSNumber trong Core Data. NSNumber rất bất tiện khi làm việc và thực hiện toán học.
Christian Schlensker

một lần nữa NSNumber không hoạt động trong khi khởi tạo bằng 0 cho giá trị rác.
Jignesh B 13/1213

xin lỗi, ...giá đỡ cho cái gì? Đó là một tham chiếu mã giả phải không? XCode thì không...
boulder_ruby

@boulder_ruby Đây ...chỉ là một trình giữ chỗ cho bất kỳ số nào bạn muốn.
Itai Ferber

126

NSNumberđối tượng là bất biến; tốt nhất bạn có thể làm là lấy giá trị nguyên thủy, tăng giá trị rồi bọc kết quả trong NSNumberđối tượng của chính nó :

NSNumber *bNumber = [NSNumber numberWithInt:[aNumber intValue] + 1];

28
Ngôn ngữ hiện đại: 1, Objective-C: 0.
devios1

77

Đối với bất kỳ ai đang sử dụng phiên bản mới nhất của Xcode (viết phiên bản này là 4.4.1, SDK 5.1), với việc sử dụng các ký tự đối tượng, bạn có thể làm sạch mã hơn một chút ...

NSNumber *x = @(1);
x = @([x intValue] + 1);
// x = 2

Vẫn còn hơi khó khăn khi đối phó với quyền anh và mở hộp mọi thứ để thực hiện các thao tác đơn giản, nhưng nó đang trở nên tốt hơn, hoặc ít nhất là ngắn hơn.


6
@softRli Hãy xem clang.llvm.org/docs/ObjectiveCLiterals.html để xem thêm objC Literals! Imo rất tiện dụng.
chown

1
Và đối với vấn đề đó, bạn có thể sử dụng x - @ (x.intValue + 1), mặc dù nhiều người không thích sử dụng ký hiệu dấu chấm để gọi các phương thức không thuộc tính. Nó ngắn hơn, nhưng có thể được gọi là lạm dụng ký hiệu dấu chấm.
Duncan C

@boulder_ruby, đó là sự chỉ định lại. Số NSN là bất biến, vì vậy để "tăng" giá trị, bạn thực sự phải gán lại nó thành một giá trị mới.
shortstuffsushi

30

NSNumbers là bất biến, bạn phải tạo một phiên bản mới.

// Work with 64 bit to support very large values
myNSNumber = [NSNumber numberWithLongLong:[myNSNumber longLongValue] + 1];

// EDIT: With modern syntax:
myNSNumber = @([myNSNumber longLongValue] + 1);

24

Đặt tất cả chúng lại với nhau và bạn có:

myNSNumber = @(myNSNumber.intValue + 1);

bạn không chỉ định lại giá trị của myNSNumber ở đây sao? Tôi nghĩ rằng không được phép vì NSNumberđối tượng là không thay đổi (?)
boulder_ruby

1
Bạn đang tạo một đối tượng NSNumber mới. myNSNumber là một con trỏ (NSNumber *) và có giá trị mới khi bạn hoàn tất.
JLundell

3

Tôi thích biểu thức dấu chấm vì nó ngắn gọn hơn và đó là lý do tại sao IOS hỗ trợ nó ngay từ đầu:

myNSNumber = [NSNumber numberWithInt:myNSNumber.intValue + 1];

ký hiệu dấu chấm không hoạt động như bạn nghĩ và đôi khi có thể chậm hơn (nó có thể được mặc định là "valueForKey:" nếu không có trình truy cập tổng hợp nào tồn tại cho "thuộc tính" (trong trường hợp của bạn là intValue). intValue chưa bao giờ được định nghĩa là @property của NSNumber.
Motti Shneor

2

Nếu bạn đang sử dụng nó để lưu trữ một giá trị tích phân:

myNSNumber = @(myNSNumber.longLongValue + 1);

Đối với nội dung dấu phẩy động, câu trả lời ngắn gọn là như sau, nhưng thực hiện điều này là một ý tưởng tồi, bạn sẽ mất độ chính xác và nếu bạn thực hiện bất kỳ loại so sánh nào sau này như [myNSNumber isEqual: @ (4.5)], bạn có thể ngạc nhiên :

myNSNumber = @(myNSNumber.floatValue + 1);

Nếu bạn cần làm toán về số dấu phẩy động được biểu diễn dưới dạng các đối tượng trong Objective-C (tức là nếu bạn cần đặt chúng trong mảng, từ điển, v.v.) thì bạn nên sử dụng NSDecimalNumber.


Nếu bạn định phản đối, cũng có thể mang tính xây dựng và nói lý do.
lms

Câu trả lời của bạn ngụ ý rằng chính NSNumber đã giới thiệu những tai ương làm tròn. Điều đó không đúng, NSNumber có hành vi làm tròn giống như các loại vô hướng. Ngoài ra lời khuyên của bạn để sử dụng NSDecimalNumbers khá khó chịu. Ở đó bạn ngụ ý rằng những thứ đó là cần thiết nếu bạn cần các đối tượng công dân đầu tiên trong onmbjective-c. Nhưng tất nhiên, số lượng ở các đối tượng là tốt. NSDecimalNumbers có độ chính xác cao hơn, nhưng lỗi làm tròn cũng có thể xảy ra với chúng. Và: op hỏi về tăng dần, câu trả lời của bạn với số học float và double. Nhưng chúng không có gia số, vì chúng không có người tiếp nhận tự nhiên.
vikingosegundo

@vikingosegundo Việc chuyển đổi NSNumber thành float gây mất độ chính xác vì NSNumber lưu trữ các số một cách trừu tượng trong đó float là base2, do đó, đó không phải là lỗi của NSNumber mà là do chuyển đổi qua lại. Và NSDecimalNumbers sẽ không gây ra lỗi làm tròn cho số học cơ số 10 và chúng được thiết kế cho số học, hãy đọc tài liệu. OP đã hỏi về việc tăng số NSN, và tôi đã cho anh ta một câu trả lời chính xác và dễ đọc cho trường hợp tích phân, đồng thời cũng đưa ra câu trả lời cho trường hợp dấu phẩy động nhưng không nên và sau đó đưa ra một gợi ý tốt hơn.
lms

Một ví dụ có thể biểu diễn 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 đến 38 chữ số và số mũ là số nguyên từ -128 đến 127. Không phải mọi số đều có thể được biểu thị như thế này. Ngoài ra OP yêu cầu gia tăng dễ dàng. NSDecimalNumber không cung cấp điều đó. và câu trả lời của bạn vẫn ngụ ý rằng bạn cần NSDecimalNumbers trong không gian đối tượng. đó là sai.
vikingosegundo

Anh bạn, tôi đang cố tỏ ra thực sự hữu ích với câu trả lời của mình và nghĩ rằng người phản đối là do tôi đã làm sai điều gì đó và tôi nghĩ mình có thể học được điều gì đó mới. Tôi có thể thấy bây giờ không phải như vậy. Nhận xét của bạn không có ý nghĩa gì và tôi khuyên bạn nên đọc các hệ thống số bởi vì hệ thống số cơ sở 10. (Re. Trích dẫn của bạn) sẽ không gây ra bất kỳ lỗi làm tròn nào cho các số cơ sở 10, tôi không nói gì về độ chính xác, chỉ là độ chính xác, nhưng 128 thập phân cũng có rất nhiều độ chính xác.
lms

0

Sử dụng một danh mục để dễ dàng sử dụng trong tương lai. Đây là một ý tưởng cơ bản.

 - (void)incrementIntBy:(int)ammount {
      self = [NSNumber numberWithInt:(self.intValue + ammount)];
 }

Ặc. Một thể loại thực hiện một phương thức thể hiện thay thế self?!? Thật là khó chịu. Tại sao không viết một phương thức thể hiện có kết quả trả về là NSNumber.
Duncan C

NSNumber được định nghĩa là bất biến, do đó, phương thức danh mục này vi phạm tính bất biến được cho là của nó (ngay cả khi thay thế self). Thay vào đó, một danh mục được thiết kế tốt hơn sẽ thêm một trình khởi tạo mới vào NSNumber, ở dạng: + numberByIncrectingAmounf: (int) amount;
Motti Shneor

0

Rất nhiều thông tin tốt trong câu trả lời cho câu hỏi này. Tôi đã sử dụng câu trả lời đã chọn trong mã của mình và nó đã hoạt động. Sau đó, tôi bắt đầu đọc phần còn lại của các bài đăng và đơn giản hóa mã rất nhiều. Sẽ khó đọc hơn một chút nếu bạn không quen với những thay đổi trong ký hiệu được giới thiệu trong Xcode 5, nhưng nó rõ ràng hơn rất nhiều. Tôi có lẽ chỉ có thể làm cho nó chỉ một dòng, nhưng sau đó hơi khó để tìm ra những gì tôi đang làm.

Tôi đang lưu trữ Số NSN trong từ điển và tôi muốn tăng nó lên. Tôi hiểu nó, chuyển nó thành int, tăng nó trong khi chuyển nó thành NSNumber, sau đó đưa nó trở lại từ điển.

Mã cũ

 NSNumber *correct = [scoringDictionary objectForKey:@"correct"];
 int correctValue = [correct intValue];
 correct = [NSNumber numberWithInt:correctValue + 1];
 [scoringDictionary removeObjectForKey:@"correct"];
 scoringDictionary[@"correct"] = correct;

Mã mới

NSNumber *correct = [scoringDictionary objectForKey:@"correct"];
scoringDictionary[@"correct"] = @(correct.intValue + 1);
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.