4 Mayıs 2015 Pazartesi

Integer Promotion

Integer Promotion Neden Var
En önemli sebebi, işlemcilere daha az instruction eklenmesini sağlaması. Aynı kural JVM ve diğer sanal makineler için de geçerli. Böylece eklenen ve değer alanları double olan toplam komutu ile tüm kayan nokta toplamaları yapılabilir. Öteki türlü double + float , double + int gibi kombinasyonların hepsi için instruction yazılması gerekirdi.

Java Dili
Java Virtual Machine Specification'da da integer promotion kavramı var. short, byte gibi tipler ile yapılan işlemer int veya long tipine yükseltilirler. Yukarıdaki açıklamayı destekleyecek şekilde gerekçelerden birisi olarak, JVM'nin daha az instruction kullanması gösterilmiş.

If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte

Ancak Java dilinde unsigned tipler yok!

Unboxing
Box'ed tipler promotion için unboxing işlemine tabi tutulurlar.

5.6.2. Binary Numeric Promotion
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:
If any operand is of a reference type, it is subjected to unboxing conversion (§5.1.8).
Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:
If either operand is of type double, the other is converted to double.

Unboxing işlemi sonucunda integer ve double yanyana gelir, integer double'a yükseltilir.
Object myObject = true ? new Integer(25) : new Double(25.0);
System.out.println(myObject);//Prints 25.0
Bu durumda çıktı olarak 25.0 alırız.

C# Dili
C# dilinde de promotion kavramı var. Buna widening deniliyor.
Kurallar şöyle: Unsigned Integer bir şekilde hem signed hem de unsigned 64 bite yükseltilebiliyor.

Integer -> Integer , Long, Decimal, Single, Double
UInteger -> UInteger , Long, ULong, Decimal, Single, Double
Örnek'teki test geçer. Çünkü b parametresi Long'a yükseltilebilir.
[TestMethod]
    public void tenEqualten()
    {
        Int64 a = 10;
        UInt32 b = 10;
        Assert.AreEqual(a, b);
    }
Bu test ise geçmez. Çünkü tabloya göre int32 uint64'e terfi edemez. Bu durumda da nesne tipleri karşılaştırılır ve test başarısız olur.
[TestMethod]
    public void tenNotEqualten()
    {
        Int32 a = 10;
        UInt64 b = 10;
        Assert.AreEqual(a, b);
    }


C Dili
C dilinde ve dolayısıyla C++ dilinde Integer Promotion tanımı şöyle

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. 58)

Integer promotion +,-, ~, bit shift gibi işlemlerde yapılır.
58) The integer promotions are applied only: as part of the usual arithmetic conversions, to certain argument expressions, to the operands of the unary +-, and ~ operators, and to both operands of the shift operators, as specified by their respective subclauses.

Integer Promotion Hataları 

1. Toplama
Örnek'te iki char toplanıyor. Sonucun char olması beklenirken integer promotion ile int'e yükseltiliyor. Sonu ise sizeof(int) yani 4
int main()
{
char a, b;
printf("%d\n", sizeof(a+b));
return 0;
}
2. Döngü
Örnek'te toplama işlemi int'e yükseltilir. Döngüden çıkmaz.


uint16_t numberA, numberB;
while ( numberA + 1 == numberB )
{
    // some processing
}

Shift
Açıklama

6.5.7 Bitwise shift operators:

  1. Each of the operands shall have integer type.
  2. The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
Örnek'te a promote edildiği için bir kaybı olmaz. b promote edilmeden tekrar atandığı için bit kaybı olur.
#include <stdio.h>

int main(void) {
    unsigned char a=0x05, b=0x05;

    // first operation
    a = ((a<<7)>>7);

    // second operation
    b <<= 7;
    b >>= 7;

    printf("a=%X b=%X\n", a, b);// a = 5 b = 1'dir
    return 0;
} 

Programlama dillerinde unsigned integer bir üst tipe iki şekilde geçirilebilir. Bunlar

  1. İşaretin muhafaza (sign preserving) edilmesi veye 
  2. değerin muhafaza (value preserving) edilmesi.


C dilinde value preserving kullanılıyor. Yani unsigned short promote edilince int'e çevrilir.

Eğer iki taraftan birisi unsigned int, diğeri ise signed int ise
İşte bu durumda integer promotion tuhaf çalışıyor ve signed int, unsigned int'e çevriliyor.

Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.
I've highlighted the passage that takes effect here and, a

Örnek'te size_t unsigned integer tipindedir. r-- ile sayı unsigned int'in alabileceği en büyük değer olan SIZE_MAX'a eşit olur.
Sağdaki -1 yukarıdaki kuraldan dolayı unsigned int'e çevrilir ve o da unsigned int'in alabileceğ en büyük değere eşitlenir. Bu durumda result = true olur.

size_t r = 0;
r--;
const bool result = (r == -1);


Signed ve Unsigned Sayıların Karışık Kullanılması
Signed ve Unsigned sayıların karışık kullanılması beklenmeyen davranışlar ortaya çıkabilir.

Hiç yorum yok:

Yorum Gönder