2015-06-15 2 views
0

Я использую кодовые блоки, и он дает другой вывод другим компиляторам, и я не могу найти решение для него. Какое неопределенное поведение в этой программе и есть ли какое-либо решение, чтобы избежать этого?Является ли i = i + 1 неопределенным поведением?

Это код для печати п-е число в системе счисления с только 3 & 4.

#include<stdio.h>                
#include<math.h>                
int main(void)                 
{                    
    int n,i,value;                
    scanf("%d",&n);                
    value=i=0;                 
    while(n>0)                 
    {                   
     if((n%2)==0)               
     {                  
      value+=4*pow(10,i);             
     }                  
     else                 
     {                  
      value+=3*pow(10,i);             
     }                  
     n=(n-1)/2;                
     i=i+1;                 
    } 
printf("\nThe number is : %d",value);                   
} 

Он отлично работает для чисел ДО 6..And выход для чисел больше 6 на единицу меньше, чем на самом деле. Например. если n = 7, выход = 332, где должно быть 333.

EDIT: При условии полного кода с фигурными скобками.

+5

Ответ на вопрос в названии действительно зависит от языка, его дизайна и спецификации. Но в общем случае 'i = i + 1' является четко определенной операцией. –

+4

Что касается вашей проблемы, это похоже на некоторый код C, а в C-вдавливании не значителен, что означает, что код в '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'находится за пределами 'else'. –

+2

Всегда используйте брекеты! Если вы не хотите работать в Apple, то есть. – Lundin

ответ

2

В этом коде нет неопределенного поведения. i=i+1; - это четко определенное поведение, которое нельзя путать с i=i++;, которое дает неопределенное поведение.

Единственное, что может вызывать различные выходы здесь, это floating point inaccuracy.

Попробуйте value += 4 * (int)nearbyint(pow(10,i)); и посмотрите, не имеет значения.

0

Кажется, что с плавающей точкой усекается.

3

вы используете функцию Pow(), которая имеет сигнатуру

double pow(double x, double y); 

и расчеты как междунар. Ошибки округления/усечения?

0

Это звучит как ошибка компилятора. Вы вычисляете результат как value+=3*pow(10,i);, но на самом деле это означает значение + = (int) (3 * pow (10, i));

Одна из двух вещей могут быть неправильно здесь:

  1. пау (10,0) = 1,0
  2. приведения к ИНТОМУ усечению результата неправильно.

Чтобы легко отладить его, просто попробуйте распечатать частичные результаты и увидеть там проблему.

0

Проблема, скорее всего, заключается в том, что функция pow на этой конкретной платформе выполняет свои вычисления, беря журнал аргумента (возможно, естественный журнал, возможно, базу данных 2), умножая на экспонента, а затем поднимая базу первый логарифм мощности этого произведения. Выполнение такой операции с числами с бесконечной точностью приведет к математически правильному результату, а также к выполнению операции с номерами с расширенной точностью и возврату результата double. Я предполагаю, что функция pow, используемая в этой реализации, может быть написана для платформы, которая могла бы выполнять промежуточные вычисления с использованием чисел с расширенной точностью и, следовательно, возвращать правильные значения двойной точности, но она запускается на платформе который не имеет расширенного типа точности. Как следствие этого, pow(10,3) может быть что-то вроде 999.9999999997 возвращения, и принуждать, что int дает 999, а не 1000.

Если вы пытаетесь получить результат целочисленного типа, нет действительно никакой причины, чтобы вычислить мощность как значение с плавающей запятой.Вместо того, чтобы вычислять 10^i внутри цикла, было бы лучше иметь переменную, которая инициализируется 1, и умножается на 10 каждый раз через цикл.