Trong java, sử dụng byte hoặc short thay vì int và float thay vì double có hiệu quả hơn không?


91

Tôi nhận thấy rằng tôi luôn sử dụng int và nhân đôi bất kể con số cần phải nhỏ hay lớn. Vậy trong java, sử dụng bytehay shortthay vì intfloatthay vì hiệu quả hơn double?

Vì vậy, giả sử tôi có một chương trình với nhiều int và gấp đôi. Nó có đáng để đi qua và thay đổi int của tôi thành byte hoặc quần short nếu tôi biết số đó sẽ phù hợp không?

Tôi biết java không có loại không dấu nhưng tôi có thể làm gì thêm nếu tôi biết số sẽ chỉ là số dương?

Theo hiệu quả, tôi chủ yếu có nghĩa là xử lý. Tôi cho rằng bộ thu gom rác sẽ nhanh hơn rất nhiều nếu tất cả các biến có kích thước bằng một nửa và các phép tính đó có lẽ cũng sẽ nhanh hơn một chút. (Tôi đoán vì tôi đang làm việc trên Android, tôi cũng cần phải lo lắng về ram)

(Tôi cho rằng trình thu gom rác chỉ xử lý các Đối tượng chứ không phải nguyên thủy nhưng vẫn xóa tất cả các nguyên thủy trong các đối tượng bị bỏ rơi đúng không?)

Tôi đã thử nó với một ứng dụng Android nhỏ mà tôi có nhưng thực sự không nhận thấy sự khác biệt nào cả. (Mặc dù tôi đã không đo lường "một cách khoa học" bất cứ điều gì.)

Tôi có sai khi cho rằng nó phải nhanh hơn và hiệu quả hơn không? Tôi ghét phải trải qua và thay đổi mọi thứ trong một chương trình lớn để phát hiện ra rằng tôi đã lãng phí thời gian của mình.

Nó có đáng làm ngay từ đầu khi tôi bắt đầu một dự án mới không? (Ý tôi là tôi nghĩ rằng từng chút một sẽ giúp ích nhưng sau đó nếu có thì tại sao có vẻ như không ai làm điều đó.)

Câu trả lời:


107

Tôi có sai khi cho rằng nó phải nhanh hơn và hiệu quả hơn không? Tôi ghét phải trải qua và thay đổi mọi thứ trong một chương trình lớn để phát hiện ra rằng tôi đã lãng phí thời gian của mình.

Câu trả lời ngắn

Vâng, bạn đã sai. Trong hầu hết các trường hợp, nó tạo ra sự khác biệt nhỏ về không gian sử dụng.

Sẽ không đáng để cố gắng tối ưu hóa điều này ... trừ khi bạn có bằng chứng rõ ràng rằng việc tối ưu hóa là cần thiết. Và nếu bạn cần tối ưu hóa việc sử dụng bộ nhớ của các trường đối tượng, có thể bạn sẽ cần phải thực hiện các biện pháp khác (hiệu quả hơn).

Câu trả lời dài hơn

Máy ảo Java lập mô hình ngăn xếp và trường đối tượng bằng cách sử dụng hiệu số (trên thực tế) là bội số của kích thước ô nguyên thủy 32 bit. Vì vậy, khi bạn khai báo một biến cục bộ hoặc trường đối tượng là (giả sử) a byte, biến / trường sẽ được lưu trữ trong một ô 32 bit, giống như một int.

Có hai ngoại lệ cho điều này:

  • longdoublegiá trị yêu cầu 2 ô 32 bit nguyên thủy
  • mảng của kiểu nguyên thủy được biểu diễn ở dạng đóng gói, để (ví dụ) một mảng byte chứa 4 byte cho mỗi từ 32 bit.

Vì vậy, nó thể đáng để tối ưu hóa việc sử dụng longdouble... và các mảng lớn các nguyên thủy. Nhưng nói chung là không.

Về lý thuyết, một JIT thể tối ưu hóa điều này, nhưng trong thực tế, tôi chưa bao giờ nghe nói về một JIT làm được điều này. Một trở ngại là JIT thường không thể chạy cho đến khi các phiên bản của lớp đang được biên dịch được tạo ra. Nếu JIT tối ưu hóa bố cục bộ nhớ, bạn có thể có hai (hoặc nhiều hơn) "hương vị" của đối tượng cùng lớp ... và điều đó sẽ gây ra khó khăn lớn.


Revisitation

Nhìn vào kết quả điểm chuẩn trong câu trả lời của @ Meriton, có vẻ như việc sử dụng shortbytethay vì intphải chịu một hình phạt về hiệu suất cho phép nhân. Thật vậy, nếu bạn xem xét các hoạt động một cách cô lập, hình phạt là đáng kể. (Bạn không nên xem xét chúng một cách cô lập ... nhưng đó là một chủ đề khác.)

Tôi nghĩ rằng lời giải thích là JIT có thể đang thực hiện các phép nhân bằng cách sử dụng các lệnh nhân 32bit trong mỗi trường hợp. Nhưng trong trường hợp byteshorttrường hợp, nó thực hiện các lệnh bổ sung để chuyển đổi giá trị 32 bit trung gian thành a bytehoặc shorttrong mỗi lần lặp vòng lặp. (Về lý thuyết, chuyển đổi đó có thể được thực hiện một lần khi kết thúc vòng lặp ... nhưng tôi nghi ngờ rằng trình tối ưu hóa có thể tìm ra điều đó.)

Dù sao, điều này chỉ ra một vấn đề khác với việc chuyển đổi sang shortbytetối ưu hóa. Nó có thể làm cho hiệu suất kém hơn ... trong một thuật toán chuyên sâu về số học và tính toán.


30
+1 không tối ưu hóa trừ khi bạn có bằng chứng rõ ràng về vấn đề hiệu suất
Bohemian

Erm, tại sao JVM phải đợi biên dịch JIT để đóng gói bố cục bộ nhớ của một lớp? Vì các loại trường được ghi vào tệp lớp, JVM không thể chọn bố cục bộ nhớ tại thời gian tải lớp, sau đó giải quyết tên trường dưới dạng byte thay vì bù từ?
Meriton

@meriton - Tôi khá chắc chắn rằng bố cục đối tượng được xác định tại thời điểm tải lớp và chúng không thay đổi sau đó. Xem phần "bản in đẹp" trong câu trả lời của tôi. Nếu bố cục bộ nhớ thực sự thay đổi khi mã được JITed, thì JVM sẽ thực sự khó xử lý. (Khi tôi nói JIT có thể tối ưu hóa bố trí, đó là giả và không thực tế ... có thể giải thích lý do tại sao tôi chưa bao giờ nghe nói về một JIT thực sự làm việc đó.)
Stephen C

Tôi biết. Tôi chỉ đang cố gắng chỉ ra rằng mặc dù bố cục bộ nhớ khó thay đổi khi các đối tượng được tạo, JVM vẫn có thể tối ưu hóa bố cục bộ nhớ trước đó, tức là tại thời gian tải lớp. Nói cách khác, thông số JVM mô tả hành vi của một JVM với các hiệu số từ không nhất thiết ngụ ý rằng một JVM bắt buộc phải được triển khai theo cách đó - mặc dù hầu hết có thể là như vậy.
khen ngợi vào

@meriton - Thông số JVM đang nói về "phép tắt từ máy ảo" trong các khung / đối tượng cục bộ. Cách chúng được ánh xạ tới hiệu số máy vật lý KHÔNG được chỉ định. Thật vậy, nó không thể chỉ định nó ... vì có thể có các yêu cầu căn chỉnh trường cụ thể cho phần cứng.
Stephen C

29

Điều đó phụ thuộc vào việc triển khai JVM, cũng như phần cứng bên dưới. Hầu hết phần cứng hiện đại sẽ không tìm nạp các byte đơn lẻ từ bộ nhớ (hoặc thậm chí từ bộ đệm cấp đầu tiên), tức là việc sử dụng các loại nguyên thủy nhỏ hơn thường không làm giảm mức tiêu thụ băng thông bộ nhớ. Tương tự như vậy, CPU hiện đại có kích thước từ là 64 bit. Chúng có thể thực hiện các hoạt động trên ít bit hơn, nhưng điều đó hoạt động bằng cách loại bỏ các bit thừa, điều này cũng không nhanh hơn.

Lợi ích duy nhất là các kiểu nguyên thủy nhỏ hơn có thể dẫn đến bố cục bộ nhớ nhỏ gọn hơn, đáng chú ý nhất là khi sử dụng mảng. Điều này tiết kiệm bộ nhớ, có thể cải thiện vị trí của tham chiếu (do đó giảm số lần bỏ lỡ bộ nhớ cache) và giảm chi phí thu gom rác.

Nói chung, tuy nhiên, sử dụng các kiểu nguyên thủy nhỏ hơn không nhanh hơn.

Để chứng minh điều đó, hãy xem điểm chuẩn sau:

package tools.bench;

import java.math.BigDecimal;

public abstract class Benchmark {

    final String name;

    public Benchmark(String name) {
        this.name = name;
    }

    abstract int run(int iterations) throws Throwable;

    private BigDecimal time() {
        try {
            int nextI = 1;
            int i;
            long duration;
            do {
                i = nextI;
                long start = System.nanoTime();
                run(i);
                duration = System.nanoTime() - start;
                nextI = (i << 1) | 1; 
            } while (duration < 100000000 && nextI > 0);
            return new BigDecimal((duration) * 1000 / i).movePointLeft(3);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }   

    @Override
    public String toString() {
        return name + "\t" + time() + " ns";
    }

    public static void main(String[] args) throws Exception {
        Benchmark[] benchmarks = {
            new Benchmark("int multiplication") {
                @Override int run(int iterations) throws Throwable {
                    int x = 1;
                    for (int i = 0; i < iterations; i++) {
                        x *= 3;
                    }
                    return x;
                }
            },
            new Benchmark("short multiplication") {                   
                @Override int run(int iterations) throws Throwable {
                    short x = 0;
                    for (int i = 0; i < iterations; i++) {
                        x *= 3;
                    }
                    return x;
                }
            },
            new Benchmark("byte multiplication") {                   
                @Override int run(int iterations) throws Throwable {
                    byte x = 0;
                    for (int i = 0; i < iterations; i++) {
                        x *= 3;
                    }
                    return x;
                }
            },
            new Benchmark("int[] traversal") {                   
                @Override int run(int iterations) throws Throwable {
                    int[] x = new int[iterations];
                    for (int i = 0; i < iterations; i++) {
                        x[i] = i;
                    }
                    return x[x[0]];
                }
            },
            new Benchmark("short[] traversal") {                   
                @Override int run(int iterations) throws Throwable {
                    short[] x = new short[iterations];
                    for (int i = 0; i < iterations; i++) {
                        x[i] = (short) i;
                    }
                    return x[x[0]];
                }
            },
            new Benchmark("byte[] traversal") {                   
                @Override int run(int iterations) throws Throwable {
                    byte[] x = new byte[iterations];
                    for (int i = 0; i < iterations; i++) {
                        x[i] = (byte) i;
                    }
                    return x[x[0]];
                }
            },
        };
        for (Benchmark bm : benchmarks) {
            System.out.println(bm);
        }
    }
}

mà in trên sổ tay hơi cũ của tôi (thêm khoảng trắng để điều chỉnh cột):

int       multiplication    1.530 ns
short     multiplication    2.105 ns
byte      multiplication    2.483 ns
int[]     traversal         5.347 ns
short[]   traversal         4.760 ns
byte[]    traversal         2.064 ns

Như bạn có thể thấy, sự khác biệt về hiệu suất là khá nhỏ. Việc tối ưu hóa các thuật toán quan trọng hơn nhiều so với việc lựa chọn kiểu nguyên thủy.


3
Thay vì nói "đáng chú ý nhất khi sử dụng mảng", tôi nghĩ có thể đơn giản hơn để nói điều đó shortbytehiệu quả hơn khi được lưu trữ trong các mảng đủ lớn để quan trọng (mảng càng lớn thì hiệu quả chênh lệch càng lớn; a byte[2]có thể nhiều hơn hoặc kém hiệu quả hơn một int[2], nhưng không đủ quan trọng), nhưng các giá trị riêng lẻ được lưu trữ hiệu quả hơn int.
supercat

2
Những gì tôi đã kiểm tra: Những điểm chuẩn đó luôn sử dụng int ('3') làm yếu tố hoặc toán hạng gán (biến thể vòng lặp, sau đó được ép kiểu). Những gì tôi đã làm là sử dụng các yếu tố được đánh máy / toán hạng gán tùy thuộc vào kiểu giá trị: int mult 76.481 ns int mult (đã gõ) 72.581 ns short mult 87.908 ns short mult (đã gõ) 90.772 ns byte mult 87.859 ns byte mult (đã gõ) 89.524 ns int [] trav 88.905 ns int [] trav (gõ) 89.126 ns short [] trav 10.563 ns short [] trav (đã gõ) 10.039 ns byte [] trav 8.356 ns byte [] trav (đã gõ) 8.338 ns Tôi cho rằng có một rất nhiều đúc không cần thiết. những thử nghiệm đó đã được chạy trên một tab Android.
Bondax

5

Sử dụng bytethay vì intcó thể tăng hiệu suất nếu bạn đang sử dụng chúng với số lượng lớn. Đây là một thử nghiệm:

import java.lang.management.*;

public class SpeedTest {

/** Get CPU time in nanoseconds. */
public static long getCpuTime() {
    ThreadMXBean bean = ManagementFactory.getThreadMXBean();
    return bean.isCurrentThreadCpuTimeSupported() ? bean
            .getCurrentThreadCpuTime() : 0L;
}

public static void main(String[] args) {
    long durationTotal = 0;
    int numberOfTests=0;

    for (int j = 1; j < 51; j++) {
        long beforeTask = getCpuTime();
        // MEASURES THIS AREA------------------------------------------
        long x = 20000000;// 20 millions
        for (long i = 0; i < x; i++) {
                           TestClass s = new TestClass(); 

        }
        // MEASURES THIS AREA------------------------------------------
        long duration = getCpuTime() - beforeTask;
        System.out.println("TEST " + j + ": duration = " + duration + "ns = "
                + (int) duration / 1000000);
        durationTotal += duration;
        numberOfTests++;
    }
    double average = durationTotal/numberOfTests;
    System.out.println("-----------------------------------");
    System.out.println("Average Duration = " + average + " ns = "
            + (int)average / 1000000 +" ms (Approximately)");


}

}

Lớp này kiểm tra tốc độ tạo mới TestClass. Mỗi bài kiểm tra thực hiện nó 20 triệu lần và có 50 bài kiểm tra.

Đây là TestClass:

 public class TestClass {
     int a1= 5;
     int a2= 5; 
     int a3= 5;
     int a4= 5; 
     int a5= 5;
     int a6= 5; 
     int a7= 5;
     int a8= 5; 
     int a9= 5;
     int a10= 5; 
     int a11= 5;
     int a12=5; 
     int a13= 5;
     int a14= 5; 
 }

Tôi đã điều hành SpeedTestlớp học và cuối cùng nhận được điều này:

 Average Duration = 8.9625E8 ns = 896 ms (Approximately)

Bây giờ tôi đang thay đổi int thành byte trong TestClass và chạy lại. Đây là kết quả:

 Average Duration = 6.94375E8 ns = 694 ms (Approximately)

Tôi tin rằng thử nghiệm này cho thấy rằng nếu bạn đang cài đặt một lượng lớn các biến, việc sử dụng byte thay vì int có thể tăng hiệu quả


4
Lưu ý rằng điểm chuẩn này chỉ đo lường chi phí liên quan đến phân bổ và xây dựng, và chỉ trong trường hợp của một lớp có nhiều trường riêng lẻ. Nếu các phép toán số học / cập nhật được thực hiện trên các trường, kết quả của @ Meriton cho thấy bytecó thể >> chậm hơn << so với int.
Stephen C

Đúng, tôi nên nói rõ hơn để làm rõ nó.
WVrock

2

byte thường được coi là 8 bit. ngắn thường được coi là 16 bit.

Trong một môi trường "thuần túy", không phải là java vì tất cả việc triển khai byte và long, và short, và những thứ thú vị khác thường bị ẩn khỏi bạn, byte tận dụng không gian tốt hơn.

Tuy nhiên, máy tính của bạn có thể không phải là 8 bit và có thể không phải là 16 bit. điều này có nghĩa là để có được 16 hoặc 8 bit cụ thể, nó sẽ cần phải dùng đến "thủ thuật" lãng phí thời gian để giả vờ rằng nó có khả năng truy cập các loại đó khi cần thiết.

Tại thời điểm này, nó phụ thuộc vào cách phần cứng được thực hiện. Tuy nhiên, theo suy nghĩ của tôi, tốc độ tốt nhất đạt được khi lưu trữ mọi thứ theo khối mà CPU của bạn có thể thoải mái sử dụng. Bộ xử lý 64 bit thích xử lý các phần tử 64 bit và bất cứ thứ gì ít hơn thế thường yêu cầu "phép thuật kỹ thuật" để giả vờ rằng nó thích xử lý chúng.


3
Tôi không chắc ý của bạn về "phép thuật kỹ thuật" ... hầu hết / tất cả các bộ xử lý hiện đại đều có hướng dẫn nhanh để tải một byte và ký-mở rộng nó, để lưu trữ một từ thanh ghi có chiều rộng đầy đủ và thực hiện theo chiều rộng byte hoặc số học chiều rộng ngắn trong một phần của thanh ghi chiều rộng đầy đủ. Nếu bạn đúng, sẽ có ý nghĩa, nếu khả thi, thay thế tất cả các int bằng long trên bộ xử lý 64-bit.
Ed Staub

Tôi có thể tưởng tượng điều đó là sự thật. Tôi chỉ nhớ rằng trong trình mô phỏng Motorola 68k mà chúng tôi đã sử dụng, hầu hết các hoạt động có thể hoạt động với các giá trị 16 bit trong khi không phải với 32 bit hay 64 bit. Tôi đã nghĩ rằng điều này có nghĩa là các hệ thống có kích thước giá trị ưu tiên mà nó có thể tìm nạp một cách tối ưu. Mặc dù tôi có thể tưởng tượng rằng các bộ xử lý 64bit hiện đại có thể tìm nạp 8bit, 16 bit, 32bit và 64bit một cách dễ dàng như nhau, nhưng trong trường hợp này thì đó là một điều không đơn giản. Cảm ơn vì đã chỉ ra điều đó.
Dmitry

"... thường được coi là ..." - Trên thực tế, rõ ràng, rõ ràng >> được chỉ định << là các kích thước đó. Trong Java. Và bối cảnh của câu hỏi này là Java.
Stephen C

Một số lượng lớn các bộ xử lý thậm chí sử dụng cùng một số chu kỳ để thao tác và truy cập dữ liệu không có kích thước bằng chữ, vì vậy nó không thực sự đáng lo ngại trừ khi bạn đo lường trên một JVM và nền tảng cụ thể.
drrob

Tôi đang cố gắng nói một cách tổng quát. Điều đó nói rằng tôi không thực sự chắc chắn về tiêu chuẩn của Java liên quan đến kích thước byte, nhưng tại thời điểm này, tôi khá thuyết phục rằng nếu bất kỳ kẻ dị giáo nào quyết định không phải byte 8 bit, Java sẽ không muốn chạm vào chúng bằng một cực mười foot. Tuy nhiên, một số bộ xử lý yêu cầu căn chỉnh nhiều byte và nếu nền tảng Java hỗ trợ chúng, nó sẽ cần làm những việc chậm hơn để xử lý các loại nhỏ hơn này hoặc biểu diễn chúng một cách kỳ diệu bằng các biểu diễn lớn hơn bạn yêu cầu. Điều đó luôn thích int hơn các loại khác vì nó luôn sử dụng kích thước yêu thích của hệ thống.
Dmitry

2

Một trong những lý do khiến short / byte / char kém hiệu quả hơn là do thiếu hỗ trợ trực tiếp cho các kiểu dữ liệu này. Bằng sự hỗ trợ trực tiếp, có nghĩa là, các đặc tả JVM không đề cập đến bất kỳ tập lệnh nào cho các kiểu dữ liệu này. Các hướng dẫn như lưu trữ, tải, thêm, v.v. có phiên bản cho kiểu dữ liệu int. Nhưng chúng không có phiên bản cho short / byte / char. Ví dụ: xem xét mã java dưới đây:

void spin() {
 int i;
 for (i = 0; i < 100; i++) {
 ; // Loop body is empty
 }
}

Tương tự được chuyển đổi thành mã máy như bên dưới.

0 iconst_0 // Push int constant 0
1 istore_1 // Store into local variable 1 (i=0)
2 goto 8 // First time through don't increment
5 iinc 1 1 // Increment local variable 1 by 1 (i++)
8 iload_1 // Push local variable 1 (i)
9 bipush 100 // Push int constant 100
11 if_icmplt 5 // Compare and loop if less than (i < 100)
14 return // Return void when done

Bây giờ, hãy xem xét việc thay đổi int thành short như bên dưới.

void sspin() {
 short i;
 for (i = 0; i < 100; i++) {
 ; // Loop body is empty
 }
}

Mã máy tương ứng sẽ thay đổi như sau:

0 iconst_0
1 istore_1
2 goto 10
5 iload_1 // The short is treated as though an int
6 iconst_1
7 iadd
8 i2s // Truncate int to short
9 istore_1
10 iload_1
11 bipush 100
13 if_icmplt 5
16 return

Như bạn có thể quan sát, để thao tác với kiểu dữ liệu ngắn, nó vẫn đang sử dụng phiên bản hướng dẫn kiểu dữ liệu int và chuyển đổi rõ ràng int thành short khi được yêu cầu. Bây giờ, do điều này, hiệu suất bị giảm.

Bây giờ, lý do được viện dẫn để không hỗ trợ trực tiếp như sau:

Máy ảo Java cung cấp hỗ trợ trực tiếp nhất cho dữ liệu kiểu int. Điều này một phần dự đoán việc triển khai hiệu quả các ngăn xếp toán hạng của Máy ảo Java và mảng biến cục bộ. Nó cũng được thúc đẩy bởi tần suất của dữ liệu int trong các chương trình điển hình. Các loại tích phân khác có ít hỗ trợ trực tiếp hơn. Ví dụ: không có byte, ký tự hoặc phiên bản ngắn của cửa hàng, tải hoặc thêm hướng dẫn.

Trích dẫn từ thông số kỹ thuật JVM có ở đây (Trang 58).


Đây là các mã bytecodes được tháo rời; tức là hướng dẫn ảo JVM . Chúng không được javactrình biên dịch tối ưu hóa và bạn không thể rút ra bất kỳ suy luận đáng tin cậy nào từ chúng về cách chương trình sẽ hoạt động trong cuộc sống thực. Trình biên dịch JIT biên dịch các mã bytecodes này thành các lệnh máy gốc thực tế và thực hiện một số tối ưu hóa khá nghiêm trọng trong quá trình này. Nếu bạn muốn phân tích hiệu suất của mã, bạn cần phải kiểm tra các hướng dẫn mã gốc. (Và nó phức tạp vì bạn cần phải tính đến hành vi thời gian của một đường ống x86_64 nhiều giai đoạn.)
Stephen C

Tôi tin rằng các thông số kỹ thuật java dành cho người triển khai javac để thực hiện. Vì vậy, tôi không nghĩ rằng có bất kỳ sự tối ưu nào được thực hiện ở cấp độ đó. Dù sao, tôi cũng có thể sai hoàn toàn. Vui lòng chia sẻ một số liên kết tham khảo để hỗ trợ tuyên bố của bạn.
Manish Bansal

Đây là một thực tế để hỗ trợ tuyên bố của tôi. Bạn sẽ không tìm thấy bất kỳ số liệu thời gian nào (đáng tin cậy) cho bạn biết mỗi lệnh JVM bytecode mất bao nhiêu chu kỳ đồng hồ. Chắc chắn không được xuất bản bởi Oracle hoặc các nhà cung cấp JVM khác. Ngoài ra, hãy đọc stackoverflow.com/questions/1397009
Stephen C,

Tôi đã tìm thấy một bài báo cũ (2008) nơi ai đó đã cố gắng phát triển một mô hình độc lập nền tảng để dự đoán hiệu suất của các chuỗi bytecode. Họ tuyên bố rằng dự đoán của họ đã sai lệch 25% so với các phép đo RDTSC .... trên Pentium. Và họ đang chạy JVM với trình biên dịch JIT bị tắt! Tham khảo: sciisedirect.com/science/article/pii/S1571066108004581
Stephen C

Tôi chỉ bối rối ở đây. Câu trả lời của tôi không phải là hỗ trợ các sự kiện mà bạn đã nêu trong phần xem xét lại?
Manish Bansal

0

Sự khác biệt là khó nhận thấy! Đó là vấn đề nhiều hơn về thiết kế, sự phù hợp, tính đồng nhất, thói quen, v.v. Đôi khi nó chỉ là vấn đề về sở thích. Khi tất cả những gì bạn quan tâm là chương trình của bạn được khởi động và chạy và việc thay thế a floatcho một intsẽ không gây hại cho tính đúng đắn, tôi thấy không có lợi khi sử dụng cái này hay cái khác trừ khi bạn có thể chứng minh rằng việc sử dụng một trong hai loại sẽ thay đổi hiệu suất. Điều chỉnh hiệu suất dựa trên các loại khác nhau trong 2 hoặc 3 byte thực sự là điều cuối cùng bạn nên quan tâm; Donald Knuth từng nói: "Tối ưu hóa sớm là gốc rễ của mọi điều xấu xa" (chưa chắc đã là anh ta, hãy chỉnh sửa nếu bạn có câu trả lời).


5
Nit: A float không thể đại diện cho tất cả các số nguyên một intcó thể; cũng không thể intđại diện cho bất kỳ giá trị không phải số nguyên nào floatcó thể. Nghĩa là, trong khi tất cả các giá trị int là một tập hợp con của các giá trị dài, thì một int không phải là một tập con của float và float không phải là một tập con của int.

Tôi hy vọng người trả lời có ý định viết substituting a float for a double, nếu vậy người trả lời nên chỉnh sửa câu trả lời. Nếu không, người trả lời nên cúi đầu xấu hổ và quay lại những điều cơ bản vì những lý do được nêu bởi @pst và vì nhiều lý do khác.
Đánh dấu hiệu suất cao

@HighPerformanceMark Không, tôi đặt int và float vì đó là những gì tôi đang nghĩ. Câu trả lời của tôi không dành riêng cho Java mặc dù tôi đã nghĩ C ... Nó có nghĩa là chung chung. Bình luận có nghĩa là bạn có ở đó.
mrk
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.