31/12/2012

Cắt số lẻ trong số double

Trong các phần mềm tài chính, ngân hàng thường có bài toán như sau:
Cho một số double, bạn hãy cắt bỏ các số lẻ sau số lẻ thứ k trong phần thập phân.
Đứng trước bài toán này bạn thường nghĩ đến giải pháp cắt chuỗi. Biến double sang NSString rồi cắt chuỗi.
Tuy nhiên khi bạn chuyển số double sang NSString bằng string format %.*f bạn sẽ gặp phải vấn đề làm tròn số lên. Bạn lại nghĩ ra vậy tôi lấy đến k+1 số lẻ rồi cắt bỏ chữ số cuối cùng.Tuy nhiên giải pháp này lại bị vấn đề làm tròn số lan truyền khi chữ số thứ k+1 là số 9. Để tránh làm tròn số lan truyền một bạn khác lại đề nghị chuyển double sang NSNumber trước khi chuyển sang NSString. Một điều không may cho giải pháp này khi bạn chuyển các số double như 1.05, 0.05 thì bạn sẽ nhận được các số 1.049999..., 0.049999,.. (xem bài viết Vấn đề làm tròn số khi dùng double). Ngoài ra bạn cũng có thể nghĩ đến các hàm C khác khi modf, ... F giới thiệu cách sử dụng hàm floor như sau:
floor(x*pow(10,k)+1E-10)/pow(10,k) 

29/12/2012

Chạy ứng dụng Android trên PC

Đọc các bài báo sau  trên báo Tuổi trẻ:

và đang suy nghĩ miên man về công nghệ mà Blue Stacks sử dụng.Ngoài ra liệu việc làm này sẽ làm cho Android mạnh lên hay sẽ thu hẹp tầm ảnh hưởng của nó?
Về công nghệ thì theo các bài báo có chút thông tin tóm tắt như sau:

  • BlueStacks sử dụng BlueStacks App Player (BAP) 
  • BAP thực hiện giải pháp chuyển đổi ảo hoá Windows/Mac OS nhanh chóng thông qua công nghệ đám mây BlueStack Cloud Connect 
  • Cho phép đồng bộ ứng dụng trên Android smartphone với PC.

VẤN ĐỀ LÀM TRÒN SỐ KHI DÙNG DOUBLE

Có bao giờ bạn gặp rắc rối khi gán 0.05 vào 1 biến double:
double f = 0.05
Rồi sau đó bạn tính
floor(f*100)
Bạn mong đợi nhận được 5. Tuy nhiên kết quả bạn nhận được lại là 4.
Để tìm hiểu nguyên nhân tại sao như vậy chúng ta bắt đầu tìm hiểu từ cách thức lưu số double trong bộ nhớ ra sau.
Số double sử dụng 8 byte hay 64 bit để lưu. Trong đó:

  • 1 bit dùng để lưu dấu của số double (sign bit)
  • 11 bit dùng để lưu độ lớn của số mũ (exponent)
  • 52 bit + 1 bit có giá trị mặc định để lưu phần định trị (mantissa)
value =(-1)sign(1.b-1b-2..b-52)2x 2e-1023=(-1)sign(SUMi=1,52(b-i2-i))x 2e-1023 trong đó e là số mũ
Vậy độ chính xác (machine epsilon) khi làm tròn là 2-53 do khoảng cách giữa hai số 2n và 2n+1 là 2n-52
Phần số mũ e được biểu diễn dạng offset-binary (excess-K) K=2n-1 với n là số bit. Ở đây n = 11.
Giá trị của số = (-1)signx 2exponent - 1023x1.mantissa
Bây giờ ta hãy xem số 0.05 lưu trong bộ nhớ ra sao?
0.05 = 0.00001100110011001100110011001100110011001100110011001100... =  0.1100110011001100110011001100110011001100110011001100... x 2-4
Phần sau dấu phẩy bị cắt 52 bít là:
110011001100110011001100110011001100110011001100110
Bây giờ bạn tính lại sẽ thấy giá trị là:
0.049999999999999988897769753748434595763683319091796875
Rõ ràng số này nhân với 100 và tính floor là 4 chứ không phải là 5.
Để lấy floor chính xác bạn cần cộng thêm một lượng 10-N. Trong đó N là số chữ số bạn quan tâm.

25/12/2012

LƯU Ý KHI RESHOW UIPOPOVERCONTROLLER

Vì một lý do nào đó bạn phải reshow lại UIPopoverController ví dụ như bạn phải canh giữa màn hình, khi đó bạn cần phải đăng ký lại các notification nếu có cho UIPopoverController này. Nếu không sau khi reshow thì  UIPopoverController không nhận notification nữa.
Ví dụ bạn muốn điều chỉnh lại kích thước của UIPopoverController mỗi khi bàn phím hiện ra chúng ta phải đăng ký nhận notification UIKeyboardWillShowNotification như sau:
//MyPopoverViewCtrl.h
@interface MyPopoverViewCtrl:UIPopoverController
-(void) reshow;
@end
//MyPopoverViewCtrl.m
@implementation MyPopoverViewCtrl
-(void) registerKeyboardEvent {
[ [NSNotificationCenter defaultCenter] addObserver:self select:@selector(doSomething:) name:UIKeyboardWillShowNotification object:nil];
}
-(void) unregisterKeyboardEvent{
[ [NSNotificationCenter defaultCenter] removeObserver:self  name:UIKeyboardWillShowNotification object:nil];
}
- (id)initWithContentViewController:(UIViewController *)viewController
self = [super initWithContentViewController:viewController];
if(self){
 [self registerKeyboardEvents];
}
return self;
}
-(void) dealloc{
[self unregisterKeyboardEvent];
[super dealloc];
}
-(void) reshow{
    [self unregisterKeyboardEvent];
   //do reshow
   [self registerKeyboardEvent];
}
-(void) doSomething:(NSNotification*)noti{
//Do what you want.
}
@end

21/12/2012

9 ỨNG DỤNG IN ẤN HÀNG ĐẦU TRÊN ANDROID

Hiện nay ở Việt Nam, điện thoại Android dần phổ biến. Một chiếc điện thoại Android thì không thể thiếu chiếc máy ảnh đi kèm. Khi chụp ảnh xong chúng ta thường tải lên các trang mạng xã hội như Facebook, Google Plus, ... Có bao giờ bạn muốn in những bức ảnh này ra máy in không? Làm cách nào để in?
Hiện nay theo F thì có các ứng dụng sau đây giúp bạn thực hiện được mong muốn này:

  1. StarPrint
    • Nội dung in: PDF, PS, văn bản trơn, nội dung trang Web, hình ảnh trong bộ sưu tập trên thiết bị, hình ảnh trên Instagram, SMS, sổ địa chỉ, thư điện tử.
    • Hỗ trợ in qua Bluetooth, Wi-Fi, USB.
    • Hỗ trợ hơn 3000 thiết bị in khác nhau của các hãng HP, Canon, Brothers, Epson, ...
  2. ePrint
    • Chỉ hỗ trợ các máy in Epson, Canon, HP.
    • Chỉ hỗ trợ Android 3.0 trở đi.
  3. Canon Easy PhotoPrint
    • Chỉ hỗ trợ máy in Canon
    • Hỗ trợ in PDF và hình tạo bởi "Canon equipment" 
  4. Epson iPrint (CyPria)
    • Chỉ hỗ trợ máy in Epson.
    • Hỗ trợ nhiều loại tập tin 
    • Có thể in từ Box, DropBox, Evernote và Google Docs.
  5. KODAK Document Print
    • Yêu cầu tài khoản "Google Cloud Print" và máy in không dây Kodak.
    • Hỗ trợ nhiều loại tập tin.
  6. Breezy-Print and Fax
    • Hỗ trợ cả iOS và Blackberry.
    • Yêu cầu "Breezy subscription".
  7. Office Max Print Center
    • Yêu cầu phải có "Office Max Network".
  8. Brother iPrint & Scan
    • Chỉ hỗ trợ máy in Brothers.
  9. HP ePrint Home & Biz
    • Chỉ hỗ trợ máy in HP. 

19/12/2012

nlctim version 2.0 release

Phiên bản 2.0 của nlctim được release vào 19/12/2012.
Phiên bản này tương thích với Yahoo! Messenger 11.5
Tải nlctim về tại http://nlctim.sf.net

09/12/2012

Student Visit Tour Document

Thời gian vừa qua Folami có cơ hội được trò chuyện với các bạn sinh viên HCMUT (cũng là các bạn đồng môn F). Nội dung chính là các bạn chuẩn bị gì để trở thành một nhà phát triển phần mềm C/C++ và một vài kinh nghiệm cho buổi phỏng vấn xin việc. Tất cả những vấn đề nêu ra đều xuất phát từ ý kiến cá nhân của F trong quá trình phỏng vấn các bạn sinh viên mới ra trường xin việc làm. Nếu có thông tin gì không đúng hay có gì muốn trao đổi với F thì đừng ngần ngại gửi email cho F.

06/12/2012

Hiển thị tập tin Freemind trong Blogger


  •  Tải visorFreemind.swf từ trang nhà của Freemind
  • Upload visorFreemind.swf lên một host miễn phí nào đó ví dụ http://www.000webhost.com. Giả sử URL của file visorFreemind.swf là http://www.example.com/visorFreemind.swf
  • Upload file Mindmap example.mm lên host tương tự như tập tin visorFreemind.swf. Giả sử URL của file này là  http://www.example.com/example.mm
  • Tạo bài viết mới trong blog của bạn chọn tab "HTML" và post nội dung bên dưới vào:
<div style="width: 100%;height:500px;">
<object data="http://www.example.com/visorFreemind.swf" height="100%" type="application/x-shockwave-flash" width="100%">
<param name="movie" value="http://www.example.com/visorFreemind.swf" />
<param name="quality" value="high" />
<param name="flashvars" value="initLoadFile=http://www.example.com/example.mm&amp;openUrl=_self&amp;startCollapsedToLevel=3&amp;maxNodeWidth=200&amp;mainNodeShape=elipse&amp;justMap=false&amp;defaultToolTipWordWrap=200&amp;offsetX=middle&amp;offsetY=middle&amp;buttonsPos=top&amp;min_alpha_buttons=20&amp;max_alpha_buttons=100&amp;scaleTooltips=false&amp;bgcolor=0xF8FBFC" />
</object>
</div>
Sau đây là một ví dụ:

05/12/2012

Những điểm mới trong XCode 4.5

Hiện nay XCode có phiên bản mới nhất là 4.5.2. So với phiên bản 4.5 thì các phiên bản 4.5.1 và 4.5.2 chủ yếu là để sửa các lỗi trong phiên bản 4.5. So với các phiên bản trước đó thì XCode 4.5 có những điểm nổi bật như sau:

  1. LLDB là trình gỡ rối mặc định thay cho GDB.
  2. Hỗ trợ OpenGL debugging & performance analysis.
  3. Auto layout.
  4. Object-C literal trong NSArray và NSDictionary.
  5. Hỗ trợ truy xuất bằng toán tử [].
  6. Hỗ trợ chuẩn C++11.
Trong các điểm này thì 4 và 5 là hai điểm hấp dẫn nhất:

  • NSNumber literals:
  // character literals.
  NSNumber *theLetterZ = @'Z';          // equivalent to [NSNumber numberWithChar:'Z']

  // integral literals.
  NSNumber *fortyTwo = @42;             // equivalent to [NSNumber numberWithInt:42]
  NSNumber *fortyTwoUnsigned = @42U;    // equivalent to [NSNumber numberWithUnsignedInt:42U]
  NSNumber *fortyTwoLong = @42L;        // equivalent to [NSNumber numberWithLong:42L]
  NSNumber *fortyTwoLongLong = @42LL;   // equivalent to [NSNumber numberWithLongLong:42LL]

  // floating point literals.
  NSNumber *piFloat = @3.141592654F;    // equivalent to [NSNumber numberWithFloat:3.141592654F]
  NSNumber *piDouble = @3.1415926535;   // equivalent to [NSNumber numberWithDouble:3.1415926535]
  // BOOL literals.
  NSNumber *yesNumber = @YES;           // equivalent to [NSNumber numberWithBool:YES]
  NSNumber *noNumber = @NO;             // equivalent to [NSNumber numberWithBool:NO]
 #ifdef __cplusplus
  NSNumber *trueNumber = @true;         // equivalent to [NSNumber numberWithBool:(BOOL)true]
  NSNumber *falseNumber = @false;       // equivalent to [NSNumber numberWithBool:(BOOL)false]
 #endif
Lưu ý:
    • Giá trị sau @ là một giá trị đơn, không chấp nhận biểu thức. Trong trường hợp cần đóng gói
      (boxing) cho một biểu thức thì sử dụng cú pháp:@(expression)
    • Đóng gói giá trị enum thì giá trị này chuyển sang kiểu của enum, nếu enum không khai báo kiểu
      thì kiều mặc định là số nguyên.
    • Đóng gói C string chuyển thành NSString với UTF8 encoding.
  • Container literals:
    • Array: NSArray*a = @[Danh sách các đối tượng ngăn cách nhau bằng dấu phẩy];
    • Dictionary: NSDictionary*b = @{ 1 danh sách các cặp @"key":object cách nhau bằng dấu phẩy}.
  • Object subscripting:
NSMutableArray *array = ...;
NSUInteger idx = ...;
id newObject = ...;
id oldObject = array[idx];
array[idx] = newObject;      // replace oldObject with newObject

NSMutableDictionary *dictionary = ...;
NSString *key = ...;
oldObject = dictionary[key];
dictionary[key] = newObject; // replace oldObject with newObject
  • Sử dụng #if __has_feature(objc_array_literals|objc_dictionary_literals|objc_subscripting) để kiểm tra chức năng này có hay không.