整数溢出以及pow()和乘法

时间:2016-03-29 16:30:15

标签: c integer-overflow

当我尝试这个乘法编译器时出现整数溢出错误

int main(){
    long long int x;
    x = 55201 * 55201;
    printf("%lld", x);
    return 0;
}

但是当我使用pow()函数执行相同的操作时,我不会收到任何错误。

int main(){
    long long int x;
    x = pow(55201, 2);
    printf("%lld", x);
    return 0;
}

为什么会这样?我必须使用第一个代码。

4 个答案:

答案 0 :(得分:3)

您需要像这样更改代码

int main(){
    long long int x;
    x = 55201LL * 55201LL;  // <--- notice the LL
    printf("%lld", x);
    return 0;
}

将乘法设为long long

当您使用pow功能时,您不会发现任何问题,因为pow使用浮点进行计算。

答案 1 :(得分:1)

这里(Linux 64bits,gcc 5.2.1),55201是一个大小为4的整数文字,表达式55201 * 55201似乎存储在4的整数中,然后才分配给你long long int

一种选择是在乘法之前将因子存储在另一个变量中,以增加范围。

int main(){
  long long int x, factor;
  factor = 55201;
  x = factor * factor;
  printf("%lld", x);
  return 0;
}

答案 2 :(得分:1)

在下面的代码中,55201默认为整数,然后相乘,结果在乘法后也是一个整数。在private void ADD_button_Click(object sender, EventArgs e) { // Getting data from DataGridView DataTable myDt = new DataTable(); myDt = GetDTfromDGV(dataGridView); // Writing to sql WriteToSQL(myDt); } private DataTable GetDTfromDGV(DataGridView dgv) { // Making our DataTable DataTable dt = new DataTable(); foreach (DataGridViewColumn column in dgv.Columns) { dt.Columns.Add(column.Name, typeof(string)); } // Getting data foreach (DataGridViewRow dgvRow in dgv.Rows) { DataRow dr = dt.NewRow(); for (int col = 0; col < dgv.Columns.Count; col++) { dr[col] = dgvRow.Cells[col].Value; } dt.Rows.Add(dr); } // removing empty rows for (int row = dt.Rows.Count - 1; row >= 0; row--) { bool flag = true; for (int col = 0; col < dt.Columns.Count; col++) { if (dt.Rows[row][col] != DBNull.Value) { flag = false; break; } } if (flag == true) { dt.Rows.RemoveAt(row); } } return dt; } private void WriteToSQL(DataTable dt) { using (SqlConnection con = new SqlConnection(sqlconn)) { SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(con); // Setting the database table name sqlBulkCopy.DestinationTableName = "[AnimalProductsCoSD].[CoSD].[ERSBusinessLogic]"; // Mapping the DataTable columns with that of the database table Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[0].ColumnName, "ERSBusinessLogic_ID")); Convert.ToString(sqlBulkCopy.ColumnMappings.Add(dt.Columns[1].ColumnName, "ERSBusinessLogic_Formula")); Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[2].ColumnName, "ERSBusinessLogic_InputsCount")); Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[3].ColumnName, "ERSBusinessLogic_Inputs")); Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[4].ColumnName, "ERSBusinessLogic_ConvFactorID")); Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[5].ColumnName, "ERSBusinessLogic_MacroID")); Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[6].ColumnName, "ERSBusinessLogic_DataSeries")); Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[7].ColumnName, "ERSBusinessLogic_InputTimeDimensionValue")); Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[8].ColumnName, "ERSBusinessLogic_InputTimeDimensionType")); Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[9].ColumnName, "ERSBusinessLogic_GeographyDimensionID")); Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[10].ColumnName, "ERSBusinessLogic_InputsUnitsIDs")); Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[11].ColumnName, "ERSBusinessLogic_Type")); Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[12].ColumnName, "ERSBusinessLogic_PrivacyID")); Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[13].ColumnName, "ERSBusinessLogic_LongDesc")); Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[14].ColumnName, "ERSBusinessLogic_InputSources")); Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[15].ColumnName, "ERSBusinessLogic_OutputName")); Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[16].ColumnName, "ERSBusinessLogic_OutputUnitID")); Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[17].ColumnName, "ERSBusinessLogic_OutputDestination")); Convert.ToString (sqlBulkCopy.ColumnMappings.Add(dt.Columns[18].ColumnName, "ERSBusinessLogic_OutputTimeDimensionValue")); Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[19].ColumnName, "ERSBusinessLogic_OutputTimeDimensionType")); Convert.ToInt32 (sqlBulkCopy.ColumnMappings.Add(dt.Columns[20].ColumnName, "ERSBusinessLogic_GroupID")); con.Open(); sqlBulkCopy.WriteToServer(dt); } } 乘法期间将计算但是它似乎溢出整数限制...这就是编译器生成警告的原因,即code optimization phase

integer overflow

int main(){ long long int x; x = 55201 * 55201; printf("%lld", x); return 0; } 声明如下:

pow

但在第二种情况下,函数double pow(double x, double y); 将每个参数都视为pow,所以现在“55201”和“2”将被隐式转换为double,现在计算发生在双精度所以计算结果后不会超过双重类型的限制......因此double

要建立相同的结果,但使用方法1可以完成如下:

the compiler will not generate any overflow message in this case.

就是这样......理解......是否有帮助。

答案 3 :(得分:0)

问题是操作是使用最大类型的操作数执行的,至少是intC standard, 6.3.1.8)。赋值只是C中的另一个表达式,=左侧的类型与右侧操作无关。

在您的平台上,两个常量都适合int,因此表达式55201 * 55201的计算结果为int。问题是结果不适合int,因此会产生溢出。

有符号整数溢出是未定义的行为。这意味着一切都会发生。幸运的是,你的编译器足够聪明,可以检测到这一点,并警告你,而不是计算机跳出窗口。简而言之:避免它!

解决方案是使用可以保存完整结果的类型执行操作。简短计算得出产品需要32位来表示。因此unsigned long就足够了。如果需要有符号整数,则需要另一位符号,即33位。这种类型现在非常罕见,所以你必须使用至少有64位的long long。 (即使它在你的平台上有64位,也不要试图使用long;这会使你的代码实现定义,因此不可移植而没有任何好处。)< / p>

为此,您需要至少其中一个操作数以获得结果类型的类型:

x = 55201LL * 55201;   // first factor is a long long constant

如果涉及变量,请使用强制转换:

long f1 = 55201;      // an int is not guaranteed to hold this value!
x = (long long)f1 * 55201;

请注意,此处不使用L后缀作为常量。它们将自动升级为最小的类型(至少int),它可以代表值。

另一个表达式x = pow(55201, 2)使用floating point function。因此,在调用double之前,参数将转换为powdouble结果由赋值运算符转换为左侧类型。

这有两个问题:

  1. 不保证double有一个63位的尾数(不包括符号),如long long。常见的IEEE754实现存在这个问题。 (这与此具体计算无关)
  2. 所有浮点运算都可能包含舍入误差,因此结果可能会偏离精确结果。这就是你必须使用第一个版本的原因。
  3. 作为一般规则,如果需要精确结果,则不应使用浮点运算。混合浮点和整数应该非常谨慎。