Поменяйте цифры в двойном в C

То, что я хочу сделать на C, - это обмен двумя цифрами в два раза.

Например, если входной сигнал равен 54321.987 и я хочу поменять второй на 4-ю цифру, выход должен быть 52341.987.

Пример, когда слишком маленький: 12.34 будет выводить 1002.34.

7 ответов

Использование метода строковой подгонки: Есть более элегантные способы, но вы можете увидеть шаги (и улучшить) этот псевдо-код, чтобы выровнять, перемещать значения и преобразовывать их обратно в число.

char buf1[20];
char buf2[20];
char *dummy;
****** val = 54321.987;
sprintf(buf1, "%9.3f", val );
//Now the number is in string form: "54321.987". Just move the two elements
buf2[0]=buf1[0];
buf2[1]=buf1[3];
buf2[2]=buf1[2];
buf2[3]=buf1[1]; //and so on
//now convert back:
val = strtod(buf2, &dummy);
printf("%9.3f\n", val);

Или, функция может быть использована для того, чтобы сделать по существу одно и то же: (все еще строение)

****** swap_num_char(****** num, int precision, int c1, int c2); //zero index for c1 and c2
int main(void)
{ ****** val = 54321.987; printf("%9.3f\n", swap_num_char(val, 3, 1, 3)); return 0;
}
****** swap_num_char(****** num, int precision, int c1, int c2)
{ char buf[25]; char format[10]; char *dummy; char c; sprintf(format, "%s0.%df", "%", precision); sprintf(buf, format, num); c = buf[c1]; buf[c1] = buf[c2]; buf[c2] = c; num = strtod(buf, &dummy); return num;
}


или используйте fmod() @John Bollinger.

Функции <code>fmod</code> вычисляют остаток с плавающей запятой <code>x/y</code>.

Извлеките 2 цифры каждый с разностью моддинга с 10 -е место и моддинга с 10-1 место.

Вычтите 2 цифры, а затем добавьте их обратно.

****** swap_digit(****** x, unsigned a, unsigned b) { printf("Before %f\n", x); ****** a_place = pow(10.0, a); ****** b_place = pow(10.0, b); ****** scaled_digit_a = fmod(x, a_place) - fmod(x, a_place/10); ****** scaled_digit_b = fmod(x, b_place) - fmod(x, b_place/10); x -= scaled_digit_a + scaled_digit_b; x += scaled_digit_a/a_place*b_place + scaled_digit_b/b_place*a_place; printf("After %f\n", x); return x;
}
int main(void) { swap_digit(54321.987,2,4); swap_digit(12.34,2,4);
}

Вывод

Before 54321.987000
After 52341.987000
Before 12.340000
After 1002.340000


Двойной хранится в памяти как последовательность бит, но вы хотите работать с десятичными цифрами. Выполняя это с ****** переменной, вы не можете получать исходные цифры из -за арифметики с плавающей запятой.

Поэтому вам следует манипулировать строковым представлением ******. Основной аспект заключается в том, сколько строк строк будет содержать. Но очевидно, что вы получаете номер от ввода. Сканируйте его как строку, а не как ******.

Существует рабочий код:

#include <stdio.h>
#include <stddef.h>
#define BUFSIZE 255
void swap_digits(char *str, int n, int m) { char *digit1 = NULL; char *digit2 = NULL; int count = 0; while (*str && (!digit1 || !digit2)) { if (*str != '.') { count++; if (count == n) { digit1 = str; } if (count == m) { digit2 = str; } } str++; } if (digit1 && digit2) { char tmp = *digit1; *digit1 = *digit2; *digit2 = tmp; }
}
int main(void) { char buffer[BUFSIZE]; scanf("%s", buffer); // it is preferably to validate input swap_digits(buffer, 2, 4); printf(buffer); return 0;
}
</stddef.h></stdio.h>


Если вы хотите, чтобы номер ввода был двойным, вы можете сделать что-то вроде этого:

#include <stdio.h> #include <stdlib.h> int main() { ****** numbergiven = 56789.1234; ****** dummy; ****** _4th_digit = (10*modf(numbergiven/10000, &dummy)) - modf(numbergiven/1000, &dummy); ****** _2th_digit = (10*modf(numbergiven/100, &dummy)) - modf(numbergiven/10, &dummy); numbergiven = numbergiven - (_4th_digit * 1000) + (_2th_digit * 1000); numbergiven = numbergiven + (_4th_digit * 10) - (_2th_digit * 10); printf("%lf",numbergiven); return 0; }
</stdlib.h></stdio.h>

Если вы не знакомы с modf, вы можете просто сделать это следующим образом:

#include <stdio.h> #include <stdlib.h> int main() { ****** numbergiven = 56789.1234; int number = numbergiven; int _4th_digit = (number/1000) - (10*(number/10000)); int _2th_digit = (number/10) - (10*(number/100)); numbergiven = numbergiven - (_4th_digit * 1000) + (_2th_digit * 1000); numbergiven = numbergiven + (_4th_digit * 10) - (_2th_digit * 10); printf("%lf",numbergiven); return 0; }
</stdlib.h></stdio.h>


1 - Используйте modf() чтобы разбить число на целые и дробные части.

****** modf(****** value, ****** *iptr);

Функции <code>modf</code> разрушают <code>value</code> аргумента на интегральную и дробную части, C11 §7.12.6.12

2 - Распечатайте целую часть в виде строки и выполните обмен.

3 - Восстановить

#include <float.h>
#include <math.h>
#include <stdio.h>
****** swap2_4digit(****** x) { if (signbit(x)) { return -swap2_4digit(-x); } printf("Before %f\n", x); ****** ipart; ****** fpart = modf(x, &ipart); // ms_digit digits '.' '\0' min_size char buf[1 + DBL_MAX_10_EXP + 1 + 1 + 4]; // Insure buffer is big enough strcpy(buf, "0000"); // Handle small numbers sprintf(buf + strlen(buf), "%.0f", ipart); size_t len = strlen(buf); char ch = buf[len - 2]; buf[len - 2] = buf[len - 4]; buf[len - 4] = ch; x = atof(buf) + fpart; printf("After %f\n", x); return x;
}
int main(void) { swap2_4digit(54321.987); swap2_4digit(12.34);
}
</stdio.h></math.h></float.h>

Вывод

Before 54321.987000
After 52341.987000
Before 12.340000
After 1002.340000

Что-то осталось для ОП. Сделать общий для других позиций цифр.


Вы можете получить две цифры, которые вас интересуют, с помощью простых операций:

Вы можете сделать это с помощью

****** x = 54321.987;
****** tens = ((int)(x / 10)) % 10; // Result is 2
****** thousands = ((int)(x / 1000)) % 10; // Result is 4

Затем вы можете вычесть цифры из их исходного места и добавить их обратно на новое место:

x = x - (tens * 10.0) - (thousands * 1000.0); // result is 50301.987
x = x + (tens * 1000.0) + (thousands * 10.0); // result is 52341.987

Теперь просто уменьшите выражение:

x = x + tens * (1000.0 - 10.0) - thousands * (1000.0 - 10.0);

Это дает вам окончательное выражение:

x += (tens - thousands) * 990.0;

Или, если вам не нужны промежуточные переменные:

x += (((int)(x/10))%10 - ((int)(x/1000))%10) * 990;


Одним из решений было бы извлечение цифр, а затем их замена.

Вы извлекаете цифры (от положительных чисел, по крайней мере), используя floor():

int place1 = 1; /* 0-based*/
****** desiredPowerOf10 = powersOf10[place1];
****** nextPowerOf10 = powersOf10[place1 + 1];
****** digit1 = floor(number / desiredPowerOf10) - floor(number/nextPowerOf10) * 10;

Затем вы можете вычесть цифры и добавить их обратно с разными полномочиями:

****** digitsRemoved = number - (digit1 * power1 + digit2 * power2);
****** digitsSwapped = digitsRemoved + digit1 * power2 + digit2 * power1;

Это может быть восприимчиво к потере точности с очень большими числами.

licensed under cc by-sa 3.0 with attribution.