byte + byte = int ... mengapa?

365

Melihat kode C # ini:

byte x = 1;
byte y = 2;
byte z = x + y; // ERROR: Cannot implicitly convert type 'int' to 'byte'

Hasil dari setiap matematika dilakukan pada byte (atau short) tipe secara implisit dilemparkan kembali ke integer. Solusinya adalah dengan secara eksplisit mengembalikan hasilnya ke byte:

byte z = (byte)(x + y); // this works

Apa yang saya pikirkan adalah mengapa? Apakah itu arsitektur? Filosofis?

Kita punya:

  • int + int =int
  • long + long =long
  • float + float =float
  • double + double =double

Jadi mengapa tidak:

  • byte + byte =byte
  • short + short = short?

Sedikit latar belakang: Saya melakukan daftar panjang perhitungan pada "angka kecil" (yaitu <8) dan menyimpan hasil antara dalam array besar. Menggunakan array byte (bukan array int) lebih cepat (karena hit cache). Tetapi byte-cast yang luas menyebar melalui kode membuatnya lebih tidak terbaca.

Robert Cartaino
sumber
10
Bukan pengetahuan Eric tentang standar yang akan berguna di sini - melainkan pengetahuannya tentang desain bahasa; apa tidak mengapa Tapi ya, jawaban Eric akan cukup definitif :)
Jon Skeet
143
Berbagai renungan di bawah ini adalah perkiraan yang masuk akal dari pertimbangan desain. Secara umum: Saya tidak menganggap byte sebagai "angka"; Saya menganggap mereka sebagai pola bit yang dapat diartikan sebagai angka, atau karakter, atau warna atau apa pun. Jika Anda akan menghitung dan memperlakukannya sebagai angka, maka masuk akal untuk memindahkan hasilnya ke tipe data yang lebih umum diartikan sebagai angka.
Eric Lippert
28
@ Eric: Itu masuk akal untuk byte, tapi mungkin tidak terlalu masuk akal untuk pendek / ushort.
Jon Skeet
23
@ Eric: byte1 | byte2sama sekali tidak memperlakukan mereka sebagai angka. Ini memperlakukan mereka dengan tepat sebagai pola bit. Saya mengerti sudut pandang Anda, tetapi kebetulan bahwa setiap kali saya melakukan aritmatika pada byte dalam C #, saya benar-benar memperlakukan mereka sebagai bit, bukan angka, dan perilaku ini selalu menghalangi.
Roman Starkov

Jawaban:

228

Baris ketiga dari cuplikan kode Anda:

byte z = x + y;

sebenarnya berarti

byte z = (int) x + (int) y;

Jadi, tidak ada operasi + pada byte, byte pertama kali dilemparkan ke bilangan bulat dan hasil penambahan dua bilangan bulat adalah bilangan bulat (32-bit).

azheglov
sumber
Saya sudah mencoba kode di bawah ini tetapi masih tidak berfungsi. byte z = (byte) x + (byte) y;
Anonim
10
itu karena tidak ada operasi + untuk byte (lihat di atas). Coba byte z = (byte) ((int) x + (int) y)
azheglov
35
Ini harus menjadi jawaban yang paling benar dan ringkas. Tidak ada operan untuk menambahkan antara byte, jadi alih-alih menjelaskan mengapa "menambahkan dua byte" berfungsi atau tidak ( tidak pernah terjadi ), ini jelas menunjukkan mengapa hasilnya adalah int, karena satu-satunya hal yang terjadi adalah penambahan 2 int .
RichardTheKiwi
2
Saya pusing membaca semua jawaban lainnya (jangan tersinggung oleh Tuan Jon Skeet). Ini saya temukan sebagai jawaban paling sederhana yang dengan tepat menggambarkan apa yang terjadi di bawah tenda. Terima kasih!
rayryeng
Inilah jawaban yang saya tulis di tempat lain yang berisi program untuk mengidentifikasi kapan promosi otomatis yang digerakkan oleh kompiler intini terjadi: stackoverflow.com/a/43578929/4561887
Gabriel Staples
172

Dalam hal "mengapa itu terjadi sama sekali" itu karena tidak ada operator yang didefinisikan oleh C # untuk aritmatika dengan byte, sbyte, pendek atau ushort, seperti yang dikatakan orang lain. Jawaban ini adalah tentang mengapa operator itu tidak didefinisikan.

Saya percaya itu pada dasarnya demi kinerja. Prosesor memiliki operasi asli untuk melakukan aritmatika dengan 32 bit dengan sangat cepat. Melakukan konversi kembali dari hasil ke byte secara otomatis bisa dilakukan, tetapi akan menghasilkan penalti kinerja dalam kasus di mana Anda tidak benar-benar menginginkan perilaku itu.

Saya pikir ini disebutkan dalam salah satu standar C # yang beranotasi. Mencari ...

EDIT: Mengganggu, saya sekarang telah melihat melalui spesifikasi ECMA C # 2 yang beranotasi, spesifikasi MS C # 3 yang beranotasi dan spesifikasi CLI anotasi, dan tidak satupun dari mereka menyebutkan ini sejauh yang saya bisa lihat. Saya yakin saya telah melihat alasan yang diberikan di atas, tetapi saya terkejut jika saya tahu di mana. Permintaan maaf, penggemar referensi :(

Jon Skeet
sumber
14
Saya minta maaf untuk mengatakan itu, tetapi saya menemukan ini bukan jawaban terbaik.
VVS
42
Sudahkah Anda menurunkan setiap jawaban yang menurut Anda bukan jawaban terbaik? ;)
Jon Skeet
55
(Hanya untuk memperjelas, saya tidak benar-benar mencoba-coba Anda. Tampaknya setiap orang memiliki kriteria mereka sendiri untuk downvoting, dan tidak apa-apa. Saya hanya menurunkan jawaban jika saya percaya itu berbahaya secara aktif daripada hanya tidak ideal. )
Jon Skeet
21
Saya menggunakan pemungutan suara sebagai instrumen untuk mendapatkan jawaban "terbaik" ke atas. Sebenarnya saya menemukan Anda tidak banyak bicara dalam jawaban Anda yang merupakan alasan utama downvote saya. Alasan lain mungkin perasaan subjektif saya bahwa perwakilan Anda memberi Anda bonus besar dalam hal pemilihan dan Anda mendapat jawaban "lebih baik".
VVS
23
IMO cara terbaik untuk mendapatkan jawaban "terbaik" ke atas adalah dengan meningkatkannya. Sejujurnya, saya pikir jawabannya paling informatif di sini adalah komentar Eric dalam pertanyaan ... tapi selain itu, untuk perspektif desain (yang bertentangan dengan "apa compiler melakukan" perspektif) Saya tidak berpikir ada adalah banyak jawaban di luar "kinerja". Secara khusus, saya benar-benar tidak membeli argumen "itu mencegah overflow" (17 suara) karena itu akan menyarankan int + int = long.
Jon Skeet
68

Saya pikir saya pernah melihat ini di suatu tempat sebelumnya. Dari artikel ini, The Old New Thing :

Misalkan kita hidup di dunia fantasi di mana operasi pada 'byte' menghasilkan 'byte'.

byte b = 32;
byte c = 240;
int i = b + c; // what is i?

Di dunia fantasi ini, nilai saya akan menjadi 16! Mengapa? Karena dua operan ke operator + keduanya byte, sehingga jumlah "b + c" dihitung sebagai byte, yang menghasilkan 16 karena overflow integer. (Dan, seperti yang saya sebutkan sebelumnya, integer overflow adalah vektor serangan keamanan baru.)

EDIT : Raymond membela, pada dasarnya, pendekatan C dan C ++ awalnya. Dalam komentarnya, dia membela fakta bahwa C # mengambil pendekatan yang sama, dengan alasan kompatibilitas mundur bahasa.

Michael Petrotta
sumber
42
Dengan bilangan bulat jika kita menambahkannya dan melimpah, itu tidak secara otomatis melemparkannya sebagai tipe data yang berbeda, jadi mengapa harus dengan byte?
Ryan
2
Dengan ints tidak meluap. Coba tambahkan int.MaxValue +1 Anda dapatkan -2147483648 alih-alih 2147483648.
David Basarab
8
@ Longhorn213: Yap, itu yang dikatakan Ryan: int matematika bisa meluap, tetapi int matematika tidak menghasilkan banyak.
Michael Petrotta
28
Persis. Jika ini dimaksudkan untuk menjadi ukuran keamanan, itu adalah salah satu yang sangat buruk diimplementasikan;)
Jon Skeet
5
@Ryan: "lazy" adalah tuduhan yang lumayan berat untuk melawan perancang bahasa C #, untuk sesuatu yang mendasar seperti matematika primitif. Jika Anda ingin menuduh mereka tentang apa pun, buatlah "kompatibilitas mundur yang berlebihan dengan C / C ++".
Michael Petrotta
58

C #

ECMA-334 menyatakan bahwa penambahan hanya didefinisikan sebagai legal pada int + int, uint + uint, panjang + panjang dan ulong + ulong (ECMA-334 14.7.4). Dengan demikian, ini adalah operasi kandidat yang harus dipertimbangkan sehubungan dengan 14.4.2. Karena ada cast implisit dari byte ke int, uint, long dan ulong, semua anggota fungsi tambahan adalah anggota fungsi yang berlaku di bawah 14.4.2.1. Kita harus menemukan pemeran tersirat terbaik menurut aturan dalam 14.4.2.3:

Casting (C1) ke int (T1) lebih baik daripada casting (C2) ke uint (T2) atau ulong (T2) karena:

  • Jika T1 adalah int dan T2 adalah uint, atau ulong, C1 adalah konversi yang lebih baik.

Casting (C1) ke int (T1) lebih baik daripada casting (C2) hingga panjang (T2) karena ada pemeran implisit dari int ke panjang:

  • Jika ada konversi implisit dari T1 ke T2, dan tidak ada konversi implisit dari T2 ke T1, C1 adalah konversi yang lebih baik.

Karenanya fungsi int + int digunakan, yang mengembalikan int.

Itu semua sangat jauh untuk mengatakan bahwa itu terkubur sangat dalam dalam spesifikasi C #.

CLI

CLI hanya beroperasi pada 6 jenis (int32, int asli, int64, F, O, dan &). (ECMA-335 partisi 3 bagian 1.5)

Byte (int8) bukan salah satu dari jenis itu, dan secara otomatis dipaksa ke int32 sebelum penambahan. (ECMA-335 partisi 3 bagian 1.6)

Alun Harford
sumber
Bahwa ECMA hanya menentukan operasi-operasi tertentu itu tidak akan mencegah bahasa dari menerapkan aturan lain. VB.NET akan membantu memungkinkan byte3 = byte1 And byte2tanpa gips, tetapi tidak membantu akan melemparkan pengecualian runtime jika int1 = byte1 + byte2menghasilkan nilai lebih dari 255. Saya tidak tahu apakah ada bahasa yang mengizinkan byte3 = byte1+byte2dan melempar pengecualian ketika itu melebihi 255, tetapi tidak melempar pengecualian jika int1 = byte1+byte2hasil nilai dalam kisaran 256-510.
supercat
26

Jawaban yang menunjukkan beberapa penambahan byte yang tidak efisien dan memotong hasilnya kembali ke byte salah. Prosesor x86 memiliki instruksi yang dirancang khusus untuk operasi integer pada kuantitas 8-bit.

Bahkan, untuk prosesor x86 / 64, melakukan operasi 32-bit atau 16-bit kurang efisien daripada operasi 64-bit atau 8-bit karena byte awalan operan yang harus diterjemahkan. Pada mesin 32-bit, melakukan operasi 16-bit memerlukan hukuman yang sama, tetapi masih ada opcode khusus untuk operasi 8-bit.

Banyak arsitektur RISC memiliki instruksi efisien kata / byte asli yang serupa. Yang umumnya tidak memiliki nilai store-and-convert-to-signed-of-some-bit-length.

Dengan kata lain, keputusan ini harus didasarkan pada persepsi untuk apa tipe byte, bukan karena inefisiensi yang mendasari perangkat keras.

Christopher
sumber
+1; jika hanya persepsi ini tidak salah setiap kali saya pernah bergeser dan OR'd dua byte di C # ...
Roman Starkov
Seharusnya tidak ada biaya kinerja untuk memotong hasilnya. Dalam rakitan x86 hanya perbedaan antara menyalin satu byte dari register atau empat byte dari register.
Jonathan Allen
1
@ JonathanAllen Persis. Satu-satunya perbedaan adalah, ironisnya, ketika melakukan konversi pelebaran . Desain saat ini dikenakan penalti kinerja untuk mengeksekusi instruksi pelebaran (baik perpanjangan yang ditandatangani atau tidak ditandatangani.)
reirab
" persepsi tentang apa tipe byte untuk " - Itu mungkin menjelaskan perilaku ini untuk byte(dan char), tetapi tidak untuk shortyang secara semantik jelas angka.
smls
13

Saya ingat pernah membaca sesuatu dari Jon Skeet (tidak dapat menemukannya sekarang, saya akan terus mencari) tentang bagaimana byte sebenarnya tidak membebani operator +. Bahkan, ketika menambahkan dua byte seperti dalam sampel Anda, setiap byte sebenarnya secara implisit dikonversi ke int. Hasil yang jelas int. Sekarang MENGAPA ini dirancang dengan cara ini, saya akan menunggu Jon Skeet sendiri untuk memposting :)

EDIT: Ditemukan! Info hebat tentang topik ini di sini .

BFree
sumber
9

Ini karena overflow dan carry.

Jika Anda menambahkan dua angka 8 bit, angka tersebut mungkin melimpah ke bit ke-9.

Contoh:

  1111 1111
+ 0000 0001
-----------
1 0000 0000

Saya tidak tahu pasti, tapi saya menganggap bahwa ints, longs, dan doublesdiberi ruang lebih karena mereka cukup besar seperti itu. Juga, mereka adalah kelipatan dari 4, yang lebih efisien bagi komputer untuk menangani, karena lebar bus data internal menjadi 4 byte atau 32 bit (64 bit semakin lazim sekarang) lebar. Byte dan pendek sedikit lebih tidak efisien, tetapi mereka dapat menghemat ruang.

samoz
sumber
23
Tetapi tipe data yang lebih besar tidak mengikuti perilaku yang sama.
Inisheer
12
Masalah meluap adalah samping. Jika Anda mengambil logika Anda dan menerapkannya ke bahasa, maka semua tipe data akan mengembalikan tipe data yang lebih besar setelah penambahan aritmatika, yang pasti BUKAN terjadi. int + int = int, panjang + panjang = panjang. Saya pikir pertanyaannya adalah sehubungan dengan inkonsistensi.
Joseph
Itu adalah pemikiran pertama saya tetapi mengapa tidak int + int = lama? Jadi saya tidak membeli argumen "mungkin overflow" ... namun <nyengir>.
Robert Cartaino
11
Oh, dan tentang "kemungkinan overflow" argeument, mengapa tidak byte + byte = pendek?
Robert Cartaino
A) Mengapa ia bekerja dengan cara kerjanya mengingat aturan C #? Lihat jawaban saya di bawah ini. B) Mengapa itu dirancang seperti itu? Mungkin hanya pertimbangan kegunaan, berdasarkan penilaian subyektif pada cara kebanyakan orang cenderung menggunakan int dan byte.
mqp
5

Dari spesifikasi bahasa C # 1.6.7.5 7.2.6.2 Promosi numerik biner ini mengubah kedua operan menjadi int jika tidak dapat masuk ke dalam beberapa kategori lain. Dugaan saya adalah mereka tidak membebani operator + untuk mengambil byte sebagai parameter tetapi ingin itu bertindak agak normal sehingga mereka hanya menggunakan tipe data int.

Bahasa C #

Ryan
sumber
4

Kecurigaan saya adalah bahwa C # sebenarnya memanggil operator+didefinisikan pada int(yang mengembalikan intkecuali Anda berada dalam checkedblok), dan secara implisit pengecoran baik dari Anda bytes/ shortske ints. Itu sebabnya perilaku itu tampak tidak konsisten.

mqp
sumber
3
Ini mendorong kedua byte pada stack, lalu memanggil perintah "add". Di IL, tambahkan "makan" dua nilai dan gantikan dengan int.
Jonathan Allen
3

Ini mungkin keputusan praktis dari para perancang bahasa. Bagaimanapun, int adalah Int32, integer bertanda 32-bit. Setiap kali Anda melakukan operasi integer pada tipe yang lebih kecil dari int, itu akan dikonversi menjadi int 32 bit oleh sebagian besar CPU 32 bit. Itu, dikombinasikan dengan kemungkinan melimpah bilangan bulat kecil, mungkin menyegel kesepakatan itu. Ini menyelamatkan Anda dari tugas untuk terus memeriksa over / under-flow, dan ketika hasil akhir dari ekspresi pada byte berada dalam jangkauan, meskipun pada beberapa tahap menengah itu akan berada di luar jangkauan, Anda mendapatkan yang benar hasil.

Pikiran lain: Over / under-flow pada tipe-tipe ini harus disimulasikan, karena tidak akan terjadi secara alami pada CPU target yang paling mungkin. Kenapa mengganggu?

PeterAllenWebb
sumber
2

Ini untuk sebagian besar jawaban saya yang berkaitan dengan topik ini, diajukan pertama ke pertanyaan serupa di sini .

Semua operasi dengan angka integral lebih kecil dari Int32 dibulatkan hingga 32 bit sebelum kalkulasi secara default. Alasan mengapa hasilnya adalah Int32 hanya untuk membiarkannya karena setelah perhitungan. Jika Anda memeriksa opcodes aritmatika MSIL, satu-satunya tipe numerik integral yang mereka gunakan adalah Int32 dan Int64. Ini "dengan desain".

Jika Anda menginginkan hasilnya kembali dalam format Int16, itu tidak relevan jika Anda melakukan kode yang dimasukkan, atau kompiler (secara hipotetis) memancarkan konversi "di bawah tenda".

Misalnya, untuk melakukan aritmatika Int16:

short a = 2, b = 3;

short c = (short) (a + b);

Dua angka akan berkembang menjadi 32 bit, ditambahkan, kemudian dipotong kembali menjadi 16 bit, seperti yang dimaksudkan MS.

Keuntungan menggunakan short (atau byte) terutama penyimpanan dalam kasus di mana Anda memiliki sejumlah besar data (data grafis, streaming, dll.)

Kenan EK
sumber
1

Tambahan tidak didefinisikan untuk byte. Jadi mereka dilemparkan ke int untuk penambahan. Ini berlaku untuk sebagian besar operasi matematika dan byte. (perhatikan ini adalah bagaimana dulu dalam bahasa yang lebih tua, saya mengasumsikan bahwa itu berlaku hari ini).

Jim C
sumber
0

Saya pikir ini adalah keputusan desain tentang operasi mana yang lebih umum ... Jika byte + byte = byte mungkin lebih banyak orang akan terganggu dengan harus melakukan cast ke int ketika sebuah int diperlukan sebagai hasilnya.

fortran
sumber
2
Saya pernah merasa terganggu dengan cara lain :) Saya sepertinya selalu membutuhkan hasil byte, jadi saya harus selalu melakukan casting.
Roman Starkov
Kecuali Anda tidak harus menggunakan int. Para pemerannya implisit. Hanya cara lain yang eksplisit.
Niki
1
@nikie, saya pikir Anda tidak mengerti jawaban saya. Jika menambahkan dua byte akan menghasilkan byte, untuk mencegah overflow seseorang harus melemparkan operan (bukan hasilnya) ke int sebelum penambahan.
fortran
0

Dari kode .NET Framework:

// bytes
private static object AddByte(byte Left, byte Right)
{
    short num = (short) (Left + Right);
    if (num > 0xff)
    {
        return num;
    }
    return (byte) num;
}

// shorts (int16)
private static object AddInt16(short Left, short Right)
{
    int num = Left + Right;
    if ((num <= 0x7fff) && (num >= -32768))
    {
        return (short) num;
    }
    return num;
}

Sederhanakan dengan .NET 3.5 dan di atasnya:

public static class Extensions 
{
    public static byte Add(this byte a, byte b)
    {
        return (byte)(a + b);
    }
}

sekarang kamu bisa melakukan:

byte a = 1, b = 2, c;
c = a.Add(b);

serio
sumber
0

Saya sudah menguji kinerja antara byte dan int.
Dengan nilai int:

class Program
{
    private int a,b,c,d,e,f;

    public Program()
    {
        a = 1;
        b = 2;
        c = (a + b);
        d = (a - b);
        e = (b / a);
        f = (c * b);
    }

    static void Main(string[] args)
    {
        int max = 10000000;
        DateTime start = DateTime.Now;
        Program[] tab = new Program[max];

        for (int i = 0; i < max; i++)
        {
            tab[i] = new Program();
        }
        DateTime stop = DateTime.Now;

        Debug.WriteLine(stop.Subtract(start).TotalSeconds);
    }
}

Dengan nilai byte:

class Program
{
    private byte a,b,c,d,e,f;

    public Program()
    {
        a = 1;
        b = 2;
        c = (byte)(a + b);
        d = (byte)(a - b);
        e = (byte)(b / a);
        f = (byte)(c * b);
    }

    static void Main(string[] args)
    {
        int max = 10000000;
        DateTime start = DateTime.Now;
        Program[] tab = new Program[max];

        for (int i = 0; i < max; i++)
        {
            tab[i] = new Program();
        }
        DateTime stop = DateTime.Now;

        Debug.WriteLine(stop.Subtract(start).TotalSeconds);
    }
}

Berikut hasilnya:
byte: 3.57s 157mo, 3.71s 171mo, 3.74s 168mo dengan CPU ~ = 30%
int: 4.05s 298mo, 3.92s 278mo, 4.28 294mo dengan CPU ~ = 27%
Kesimpulan:
byte menggunakan lebih banyak CPU tetapi les memori dan lebih cepat (mungkin karena ada byte lebih sedikit untuk dialokasikan)

puipuix
sumber
-1

Selain semua komentar hebat lainnya, saya pikir saya akan menambahkan satu berita kecil. Banyak komentar bertanya-tanya mengapa int, panjang, dan hampir semua tipe numerik lainnya tidak juga mengikuti aturan ini ... mengembalikan tipe "lebih besar" sebagai respons terhadap aritmatika.

Banyak jawaban berkaitan dengan kinerja (well, 32bit lebih cepat dari 8bit). Pada kenyataannya, angka 8bit masih merupakan angka 32bit ke CPU 32bit .... bahkan jika Anda menambahkan dua byte, potongan data yang beroperasi cpu akan menjadi 32bits terlepas ... jadi menambahkan ints tidak akan menjadi "lebih cepat" daripada menambahkan dua byte ... semuanya sama dengan cpu. SEKARANG, menambahkan dua int AKAN lebih cepat daripada menambahkan dua lama pada prosesor 32bit, karena menambahkan dua lama membutuhkan lebih banyak microops karena Anda bekerja dengan angka yang lebih luas daripada kata prosesor.

Saya pikir alasan mendasar untuk menyebabkan byte aritmatika untuk menghasilkan int cukup jelas dan lurus ke depan: 8bits tidak terlalu jauh! : D Dengan 8 bit, Anda memiliki rentang 0-255 yang tidak ditandatangani. Itu tidak banyak ruang untuk bekerja dengan ... kemungkinan bahwa Anda akan mengalami keterbatasan byte SANGAT tinggi ketika menggunakannya dalam aritmatika. Namun, kemungkinan Anda kehabisan bit ketika bekerja dengan int, atau long, atau dobel, dll. Secara signifikan lebih rendah ... cukup rendah sehingga kami jarang sekali menemukan kebutuhan untuk lebih.

Konversi otomatis dari byte ke int adalah logis karena skala byte sangat kecil. Konversi otomatis dari int ke long, float ke double, dll. Tidak logis karena angka-angka tersebut memiliki skala yang signifikan.

jrista
sumber
Ini masih tidak menjelaskan mengapa byte - bytekembali int, atau mengapa mereka tidak memberikan short...
KthProg
Mengapa Anda ingin penambahan untuk mengembalikan jenis yang berbeda dari pengurangan? Jika byte + bytekembali int, karena 255 + apa pun lebih besar dari satu byte dapat menampung, tidak masuk akal untuk memiliki byte dikurangi byte lain mengembalikan apa pun selain int dari sudut pandang konsistensi jenis kembali.
jrista
Saya tidak mau, itu hanya menunjukkan bahwa alasan di atas mungkin tidak benar. Jika itu ada hubungannya dengan "fitting" ke dalam hasil, maka bytepengurangan akan mengembalikan a byte, dan penambahan byte akan mengembalikan a short( byte+ byteakan selalu masuk ke dalam a short). Jika itu tentang konsistensi seperti yang Anda katakan, maka shortmasih cukup untuk kedua operasi daripada int. Jelas ada campuran alasan, tidak semuanya dipikirkan dengan matang. Atau, alasan kinerja yang diberikan di bawah ini mungkin lebih akurat.
KthProg