Поменяйте цифры в двойном в 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.

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

Извлеките 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);

Функции modf разрушают value аргумента на интегральную и дробную части, 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.