[C언어] -0이 표시되는 이유와 없애는 방법 좀 알려주세요 ㅠㅠ

익명 사용자의 이미지

#include

int main(void)
{
int a[3][3], b[3][3], c[3][3], d[3][3];
int i, j, k;
float detA, invA[3][3];

printf("행렬 A 입력\n");
for (i = 0; i < 3; i++) //첫번째 행렬 입력
{
printf("%d행 => ", i + 1);
for (j = 0; j < 3; j++)scanf_s("%d", &a[i][j]);
}
printf("행렬 B 입력\n");
for (i = 0; i < 3; i++) //두번째 행렬 입력
{
printf("%d행 => ", i + 1);
for (j = 0; j < 3; j++)scanf_s("%d", &b[i][j]);
}
printf(" %d %d %d %d %d %d\n", a[0][0], a[0][1], a[0][2], b[0][0], b[0][1], b[0][2]);
printf("A = %d %d %d B = %d %d %d\n", a[1][0], a[1][1], a[1][2], b[1][0], b[1][1], b[1][2]);
printf(" %d %d %d %d %d %d\n", a[2][0], a[2][1], a[2][2], b[2][0], b[2][1], b[2][2]);
printf("----------------------\n");
for (i = 0; i < 3; i++) //행렬의 합 계산
{
for (j = 0; j < 3; j++)
c[i][j] = a[i][j] + b[i][j];
}
for (i = 0; i < 3; i++) //합의 결과 출력
{
for (j = 0; j < 3; j++)
{
if (i == 1 && j == 0)
printf("A + B = %d", c[i][j]);
else if (j == 0 && (i == 0 || i == 2))
printf(" %d", c[i][j]);
else
printf(" %d", c[i][j]);
}
printf("\n");
}
printf("--------------\n");
for (i = 0; i < 3; i++) //행렬의 곱 계산
{
for (j = 0; j < 3; j++)
{
d[i][j] = 0;
for (k = 0; k < 3; k++)
{
d[i][j] += a[i][k] * b[k][j];
}
}
}
for (i = 0; i < 3; i++) //곱의 결과 출력
{
for (j = 0; j < 3; j++)
{
if (i == 1 && j == 0)
printf("A * B = %d", d[i][j]);
else if (j == 0 && (i == 0 || i == 2))
printf(" %d", d[i][j]);
else
printf(" %d", d[i][j]);
}
printf("\n");
}
printf("--------------\n");
/*역행렬 계산*/
detA = a[0][0] * a[1][1] * a[2][2] - a[0][0] * a[1][2] * a[2][1]
+ a[0][1] * a[1][2] * a[2][0] - a[0][1] * a[1][0] * a[2][2]
+ a[0][2] * a[1][0] * a[2][1] - a[0][2] * a[1][1] * a[2][0];

invA[0][0] = (1 / detA) * (a[1][1] * a[2][2] - a[1][2] * a[2][1]);
invA[0][1] = (1 / detA) * (a[0][2] * a[2][1] - a[0][1] * a[2][2]);
invA[0][2] = (1 / detA) * (a[0][1] * a[1][2] - a[0][2] * a[1][1]);
invA[1][0] = (1 / detA) * (a[1][2] * a[2][0] - a[0][1] * a[2][2]);
invA[1][1] = (1 / detA) * (a[0][0] * a[2][2] - a[0][2] * a[2][0]);
invA[1][2] = (1 / detA) * (a[0][2] * a[1][0] - a[0][0] * a[1][2]);
invA[2][0] = (1 / detA) * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
invA[2][1] = (1 / detA) * (a[0][1] * a[2][0] - a[0][0] * a[2][1]);
invA[2][2] = (1 / detA) * (a[0][0] * a[1][1] - a[0][1] * a[1][0]);

for (i = 0; i < 3; i++) //역행렬의 결과 출력
{
for (j = 0; j < 3; j++)
{
if (i == 1 && j == 0)
printf("A^-1 = %.0f", invA[i][j]);
else if (j == 0 && (i == 0 || i == 2))
printf(" %.0f", invA[i][j]);
else
printf(" %.0f", invA[i][j]);
}
printf("\n");
}
return 0;
}

자료형 선언의 문제인가요? double, long double도 해봤는데
역행렬을 구하는 과정에서 자꾸 -0 이 나오네요ㅠㅠ
원인과 해결방법이 궁금합니다!

세벌의 이미지

리눅스에서

gcc -Wall -o a a.c

했더니
scanf_s
모르겠다고 하네요.

kldp 에서는 소스코드는 code 로 감싸야 들여쓰기 안 깨집니다.

더하기 곱하기는 잘 되나요?

detA가 0일 때는 어떻게 되죠?

https://en.wikipedia.org/wiki/Signed_zero 참고하시고.

질문을 잘 정리하다보면 답에 가까이 갈 수 있을 겁니다.

익명 사용자의 이미지

gdb 로 한단계씩 실행해 보세요.
이럴때 쓰라고 gdb 가 있는건데.
C 는 gdb 사용하지 않고는 제대로 하기 어려워요.

익명 사용자의 이미지

ieee754 부동소수점 형식에서 음수를 표기하는 방식에 따른 artifact입니다.

아시겠지만, ieee754 부동소수점 형식은 수를 "부호 비트" + "절대값"으로 나타내지요.
그런 구조에서는 어쩔 수 없이 0을 두 가지 표현으로 나타낼 수 있게 됩니다: +0과 -0.

게다가, 연산 결과로서 -0이 나오는 경우를 허용함으로써, 부동소수점 연산을 조금이나마 더 간단하게 구현할 수 있는 경우가 있어요.
아래와 같은 경우를 보시길.

https://ideone.com/MQS7ft

뭐, 어쨌거나 틀린 결과는 아니지 않습니까?
+0이 -0과 같다는 걸 우리도 알고 컴퓨터도 아는 걸요.

꼭 그렇게 박멸해야겠다고 생각하시는 이유를 잘 모르겠습니다. 그냥 보기 싫어서 그런가요?

Hyun의 이미지

https://ideone.com/JbQMme
+0, -0 이 다르다고 판단해야 하는 경우는 memcmp() 를 사용해야겠네요...

익명 사용자의 이미지

그것도 방법입니다.

확인하신 것과 같이, 바이트열 레벨에서는 +0.0과 -0.0이 분명 다르니까요. 부호 비트 하나 차이입니다만.

C99부터는 좀 더 명시적인 방법으로 구분할 수도 있습니다. 아래 코드를 보시죠.

#include <stdio.h>
#include <math.h>
 
int main(void) {
	double d1 = 1. * 0.;
	double d2 = (-1.) * 0;
 
	printf("d1: %f\n", d1);
	printf("d2: %f\n", d2);
 
	printf("d1 == d2: %s\n", (d1 == d2)?"true":"false");
 
	printf("signbit(d1) != 0: %d\n", (int)(signbit(d1) != 0));
	printf("signbit(d2) != 0: %d\n", (int)(signbit(d2) != 0));
 
	printf("copysign(1., d1): %f\n", copysign(1., d1));
	printf("copysign(1., d2): %f\n", copysign(1., d2));
	return 0;
}

실행 결과: https://ideone.com/Rmo5LQ

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.