Chuyển đổi số thập phân thành gấp đôi


671

Tôi muốn sử dụng một Track-Barđể thay đổi Formđộ mờ đục.

Đây là mã của tôi:

decimal trans = trackBar1.Value / 5000;
this.Opacity = trans;

Khi tôi xây dựng ứng dụng, nó sẽ báo lỗi sau:

Không thể ngầm chuyển đổi loại decimalthànhdouble

Tôi đã thử sử dụng transdoublesau đó Controlkhông hoạt động. Mã này hoạt động tốt trong một dự án VB.NET trước đây.


11
Ngoài ra, Decimal không thể biểu thị giá trị rộng bằng Double. Số thập phân chỉ có thể lên tới +/- 7.9228162514264337593543950335E + 28; trong khi Double có thể lên tới +/- 1.79769313486232E + 308
TraumaPony


7
Ai đó nên đánh dấu cái này là một bản sao.
Ivan

7
@Ivan: Đây là câu hỏi thứ 4 được hỏi trên SO bao giờ ...
Nikolas

1
@Nikolas: Thật vậy. Truy tìm ở đây ngày hôm nay.
Tháng Sáu

Câu trả lời:


446

Một diễn viên rõ ràng để doublethích điều này là không cần thiết:

double trans = (double) trackBar1.Value / 5000.0;

Xác định hằng số là 5000.0(hoặc như 5000d) là đủ:

double trans = trackBar1.Value / 5000.0;
double trans = trackBar1.Value / 5000d;

123

Một câu trả lời chung chung hơn cho câu hỏi chung "Số thập phân so với gấp đôi?": Số thập phân cho các tính toán tiền tệ để duy trì độ chính xác, Nhân đôi cho các tính toán khoa học không bị ảnh hưởng bởi những khác biệt nhỏ. Vì Double là loại có nguồn gốc từ CPU (biểu diễn bên trong được lưu trữ trong cơ sở 2 ), các tính toán được thực hiện với Double hoạt động tốt hơn sau đó là Decimal (được thể hiện trong cơ sở 10 bên trong).


83

Mã của bạn hoạt động tốt trong VB.NET vì nó hoàn toàn không sử dụng bất kỳ phôi nào, trong khi C # có cả ẩn và rõ ràng.

Trong C #, việc chuyển đổi từ thập phân thành gấp đôi là rõ ràng khi bạn mất độ chính xác. Ví dụ 1.1 không thể được biểu thị chính xác dưới dạng gấp đôi, nhưng có thể là số thập phân (xem " Số dấu phẩy động - không chính xác hơn bạn nghĩ " vì lý do tại sao).

Trong VB, trình chuyển đổi đã được thêm vào cho bạn bởi trình biên dịch:

decimal trans = trackBar1.Value / 5000m;
this.Opacity = (double) trans;

Điều đó (double)phải được nêu rõ trong C #, nhưng có thể được hàm ý bởi trình biên dịch 'tha thứ' hơn của VB.


80

Tại sao bạn chia cho 5000? Chỉ cần đặt giá trị Tối thiểu và Tối đa của TrackBar trong khoảng từ 0 đến 100, sau đó chia Giá trị cho 100 cho phần trăm Độ mờ. Ví dụ tối thiểu 20 dưới đây ngăn không cho biểu mẫu trở nên hoàn toàn vô hình:

private void Form1_Load(object sender, System.EventArgs e)
{
    TrackBar1.Minimum = 20;
    TrackBar1.Maximum = 100;

    TrackBar1.LargeChange = 10;
    TrackBar1.SmallChange = 1;
    TrackBar1.TickFrequency = 5;
}

private void TrackBar1_Scroll(object sender, System.EventArgs e)
{
    this.Opacity = TrackBar1.Value / 100;
}

5
Điều này sẽ không di chuyển vấn đề xung quanh? Thay vì một vấn đề với 5000, OP sẽ có vấn đề với 100?
jww

62

Bạn có hai vấn đề. Đầu tiên, Opacityyêu cầu gấp đôi, không phải giá trị thập phân. Trình biên dịch đang nói với bạn rằng trong khi có một chuyển đổi giữa thập phân và kép, thì đó là một chuyển đổi rõ ràng mà bạn cần chỉ định để nó hoạt động. Thứ hai là TrackBar.Valuemột giá trị nguyên và chia một int cho một kết quả int trong một int cho dù bạn gán nó cho loại biến nào. Trong trường hợp này, có một phân phối ngầm định từ int đến thập phân hoặc gấp đôi - bởi vì không có độ chính xác khi bạn thực hiện phân vai - vì vậy trình biên dịch không phàn nàn, nhưng giá trị bạn nhận được luôn là 0, có lẽ, vìtrackBar.Valueluôn luôn nhỏ hơn 5000. Giải pháp là thay đổi mã của bạn để sử dụng gấp đôi (loại gốc cho Opacity) và thực hiện số học dấu phẩy động bằng cách biến hằng số thành một số kép - sẽ có tác dụng thúc đẩy số học - hoặc truyền trackBar.Valuelên gấp đôi , sẽ làm điều tương tự - hoặc cả hai. Ồ, và bạn không cần biến trung gian trừ khi nó được sử dụng ở nơi khác. Tôi đoán là trình biên dịch sẽ tối ưu hóa nó đi, dù sao.

trackBar.Opacity = (double)trackBar.Value / 5000.0;

58

Theo tôi, nó là mong muốn được rõ ràng nhất có thể. Điều này thêm sự rõ ràng vào mã và hỗ trợ các lập trình viên đồng nghiệp của bạn, những người cuối cùng có thể đọc nó.

Ngoài (hoặc thay vì) nối thêm .0số vào số, bạn có thể sử dụng decimal.ToDouble().

Dưới đây là một số ví dụ:

// Example 1
double transperancy = trackBar1.Value/5000;
this.Opacity = decimal.ToDouble(transperancy);

// Example 2 - with inline temp
this.Opacity = decimal.ToDouble(trackBar1.Value/5000);

57

Nghe có vẻ như this.Opacitylà một giá trị kép và trình biên dịch không giống như bạn đang cố nhồi nhét một giá trị thập phân vào nó.


50

Các Opacity tài sản là loại kép:

double trans = trackBar1.Value / 5000.0;
this.Opacity = trans;

hoặc đơn giản:

this.Opacity = trackBar1.Value / 5000.0;

hoặc là:

this.Opacity = trackBar1.Value / 5000d;

Lưu ý rằng tôi đang sử dụng 5000.0(hoặc 5000d) để buộc một phép chia kép vì trackBar1.Valuelà một số nguyên và nó sẽ thực hiện phép chia số nguyên và kết quả sẽ là một số nguyên.



47

Giả sử bạn đang sử dụng WinForms, Form.Opacitythuộc loại double, vì vậy bạn nên sử dụng:

double trans = trackBar1.Value / 5000.0;
this.Opacity = trans;

Trừ khi bạn cần giá trị ở nơi khác, viết đơn giản hơn:

this.Opacity = trackBar1.Value / 5000.0;

Lý do điều khiển không hoạt động khi bạn thay đổi mã của mình thành đơn giản là vì bạn có:

double trans = trackbar1.Value / 5000;

trong đó diễn giải 5000là số nguyên và vì đó trackbar1.Valuecũng là số nguyên nên transgiá trị của bạn luôn bằng không. Bằng cách làm rõ ràng giá trị số một giá trị dấu phẩy động bằng cách thêm .0trình biên dịch giờ đây có thể hiểu nó là một giá trị kép và thực hiện phép tính thích hợp.


41

Giải pháp tốt nhất là:

this.Opacity = decimal.ToDouble(trackBar1.Value/5000);

41

Opacitylà một giá trị kép, tôi sẽ chỉ sử dụng gấp đôi từ đầu và hoàn toàn không sử dụng, nhưng hãy chắc chắn sử dụng gấp đôi khi chia để bạn không mất bất kỳ độ chính xác nào

Opacity = trackBar1.Value / 5000.0;

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.