2017-10-04 68 views
2

我想在C中做的是在双精度交换两位数。在C中双位交换数字

例如,如果输入是54321.987而我想将第二位与第四位交换,则输出应为52341.987

示例太小时:12.34会输出1002.34

+10

字符串化它。交换字符,解开它。 sprintf(),sscanf()。 –

+0

如果它是一个编程任务,并且您不想将其串化。首先在提醒时使用模10功能提取所有数字。 然后检查相应的第2位和第4位。 例如:n = 12345.678。使用'n-n%1'提取小数部分 用'n-n%10'获取最后一位数字,然后用n除以10,同样得到下一位数字,依此类推。 –

+1

..或者你可以用mult/div重复10次做一些明确的,讨厌的loopy/recursivey事情。 –

回答

0

使用字符串化的方法:
有更优雅的方式,但可以看到的步骤(和改善)这个伪代码字符串化,移动值,并将其转换回数字。

char buf1[20]; 
char buf2[20]; 
char *dummy; 
double 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); 

或者,函数可用于基本上做同样的事情:(仍然字串)

double swap_num_char(double num, int precision, int c1, int c2); //zero index for c1 and c2 


int main(void) 
{ 

    double val = 54321.987; 

    printf("%9.3f\n", swap_num_char(val, 3, 1, 3)); 

    return 0; 
} 

double swap_num_char(double 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; 
} 
0

如果你想输入数字双待,那么你可以做这样的事情:

#include <stdio.h> 
    #include <stdlib.h> 

    int main() 
    { 
     double numbergiven = 56789.1234; 
     double dummy; 
     double _4th_digit = (10*modf(numbergiven/10000, &dummy)) - modf(numbergiven/1000, &dummy); 
     double _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; 
    } 

如果你不熟悉MODF那么你可以简单地这样来做:

#include <stdio.h> 
    #include <stdlib.h> 

    int main() 
    { 
     double 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; 
    } 
+0

@chux我刚刚根据你的建议编辑了代码,是否有新的错误? –

+0

我认为用双傀儡会更清楚; double _4th_digit =(10 * modf(numbergiven/10000,&dummy)) - modf(numbergiven/1000,&dummy);' – chux

0

你可以得到两个数字,你有兴趣与简单的操作:

您可以

double x = 54321.987; 
double tens = ((int)(x/10)) % 10;  // Result is 2 
double 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; 
+0

细节'(int)(x/10)'是UB的大'双'。 OP可能不关心所有'double'的代码。 – chux

0

一个解决办法是提取数字,然后交换他们。

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

然后,您可以减去的数字,并与不同的权力将其添加回:

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

通过使用地板()提取数字(至少从正数)

虽然这可能会导致精度损失非常大的数字。

0

1 - 使用modf()将数字拆分为整数和小数部分。

double modf(double value, double *iptr); 

modf功能打破参数value分为整数和小数部分,C11§7.12.6.12

2 - 打印整数部分作为一个字符串,并执行交换。

3 - 重建离开OP

#include <float.h> 
#include <math.h> 
#include <stdio.h> 

double swap2_4digit(double x) { 
    if (signbit(x)) { 
    return -swap2_4digit(-x); 
    } 
    printf("Before %f\n", x); 
    double ipart; 
    double 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); 
} 

输出

Before 54321.987000 
After 52341.987000 
Before 12.340000 
After 1002.340000 

东西。做一般的其他数字位置。

0

Double以位序列的形式存储在存储器中,但您希望使用十进制数字进行操作。这样做与double变量您可能不会收到原始数字,因为floating-point arithmetic

因此,您应该使用double的字符串表示进行操作。主要方面是多少个数字字符串将包含。但很明显,你从输入中得到数字。扫描它作为字符串,而不是double

有一个工作代码:

#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; 
} 
0

或使用fmod()@John Bollinger

fmod函数计算x/y的浮点剩余部分。

提取2位每改装的具有10 地方差和改装用10 地方-1

减去2位数字,然后将它们添加回交换。

double swap_digit(double x, unsigned a, unsigned b) { 
    printf("Before %f\n", x); 
    double a_place = pow(10.0, a); 
    double b_place = pow(10.0, b); 
    double scaled_digit_a = fmod(x, a_place) - fmod(x, a_place/10); 
    double 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