掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.24292

数型を文字配列へ変換したい
投稿者---miz(2005/11/21 22:19:29)


はじめまして。
intやfloatなどの数型?を文字配列に変換する関数を自作したいのですが
良いアイディアはありませんでしょうか?
ちょっと分かりづらいと思いますが、sprintfを使って変換するのと
等価の関数を作りたいです。

よろしくお願いいたします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> 環境を書き忘れました。 24293 miz 2005/11/21 22:38:37
<子記事> Re:数型を文字配列へ変換したい 24295 Blue 2005/11/21 22:51:52


No.24293

環境を書き忘れました。
投稿者---miz(2005/11/21 22:38:37)


VC++6.0 WinXP です。


この投稿にコメントする

削除パスワード

No.24295

Re:数型を文字配列へ変換したい
投稿者---Blue(2005/11/21 22:51:52)


一桁の数値を文字にすることは出来ますか?
それが出来れば、各桁にその処理をして、文字列化するだけです。



この投稿にコメントする

削除パスワード

No.24296

Re:数型を文字配列へ変換したい
投稿者---miz(2005/11/21 22:58:17)


>一桁の数値を文字にすることは出来ますか?
はい。一桁であればchar型に変換できます。
しかし連続する数字の場合それを一つ一つの数字に分解できないのですが
その方法をご教授願えますか?


この投稿にコメントする

削除パスワード

No.24298

Re:数型を文字配列へ変換したい
投稿者---Blue(2005/11/21 23:14:18)


> しかし連続する数字の場合それを一つ一つの数字に分解できないのですが
> その方法をご教授願えますか?

1234の場合

1000の位・・・1
 100の位・・・2
  10の位・・・3
   1の位・・・4

ということなので、各桁の数値は10nの商ということはわかりますか?
それをfor文かなんかで書くだけです。(まずは整数のみ考える)



この投稿にコメントする

削除パスワード

No.24299

Re:数型を文字配列へ変換したい
投稿者---miz(2005/11/21 23:20:37)


どうもありがとうございます。
分かりました。その処理は最初に思いついたのですが、もう少しシンプルな方法が無いかと思いまして・・・。
コーディングしてみます。



この投稿にコメントする

削除パスワード

No.24328

作ってみましたが、挙動がおかしいです。
投稿者---miz(2005/11/23 18:37:30)


小数部だけを配列に格納するように作ったのですが、変換する値fを12.34で変換すると0.3399999999になってしまいます。
しかし0.34で変換すると正常に変換されます。
各変数を見てみると分解して配列に格納するルーチンの前で
fはいずれの時も0.34となっているのですが挙動が違います。
これはなぜでしょうか?
よろしくお願いいたします。

#include "stdafx.h"

int main(int argc, char* argv[])
{
    int n,m,sum_f[10];
    double f=12.34;
    //配列初期化

    for(n=0;n<10;++n)
        sum_f[n]=0;

    //小数部に分解する

    n=f;
    f=f-n;

    //小数部を一桁ずつに分解してsum_fに格納

    for(m=0;m<10;++m){
        f=f*10;
        sum_f[m]=f;
        f=f-sum_f[m];
    }
    //表示

    printf("0.");
    for(m=0;m<10;++m){
        printf("%d",sum_f[m]);
    }
    }



この投稿にコメントする

削除パスワード

No.24330

Re:作ってみましたが、挙動がおかしいです。
投稿者---まきじ(2005/11/23 18:53:08)


>小数部だけを配列に格納するように作ったのですが、変換する値fを12.34で変換すると0.3399999999になってしまいます。
>f=f-n;

浮動小数点の計算は誤差が生じる為、その様な値となってしまいます。


この投稿にコメントする

削除パスワード

No.24331

Re:作ってみましたが、挙動がおかしいです。
投稿者---miz(2005/11/23 18:56:14)


回答ありがとうございます。

何か対策方法は無いでしょうか?


この投稿にコメントする

削除パスワード

No.24332

追記です。
投稿者---miz(2005/11/23 19:04:25)


0.34 OK
12.34 NG
122.34 OK
1222.34 NG
12222.34 OK
・・・

と整数部が奇数のときだけ起こるようですが、どうしてでしょうか?


この投稿にコメントする

削除パスワード

No.24336

Re:追記です。
投稿者---REE(2005/11/23 19:42:41)


>と整数部が奇数のときだけ起こるようですが、どうしてでしょうか?

偶数桁の間違い?
それはさておき、既に言われているように、「浮動小数点の計算は誤差が生じる為」です。



この投稿にコメントする

削除パスワード

No.24337

Re:追記です。
投稿者---miz(2005/11/23 19:55:29)


失礼しました、偶数桁の間違いです。

>それはさておき、既に言われているように、「浮動小数点の計算は誤差が生じる為」です。

今回の場合、12.34-12=? という計算を行っておりますが、これがどのような値に化けているのでしょうか?fをprintfしてみて表示された値はどちらも差が無かったのですが、目には見えない誤差という事でしょうか?
また、それを表示する方法は有りますか?




この投稿にコメントする

削除パスワード

No.24340

Re:追記です。
投稿者---REE(2005/11/23 20:11:28)


>今回の場合、12.34-12=? という計算を行っておりますが、これがどのような値に化けているのでしょうか?fをprintfしてみて表示された値はどちらも差が無かったのですが、目には見えない誤差という事でしょうか?

12.34を2進数で表現してみてください。
誤差の正体が見えてくるかもしれません。

>また、それを表示する方法は有りますか?

printfでも、書式指定で、小数点以下の桁数を多く表示すれば見えてくるかもしれません。




この投稿にコメントする

削除パスワード

No.24341

Re:追記です。
投稿者---まきじ(2005/11/23 20:15:47)


浮動小数点 誤差


この投稿にコメントする

削除パスワード

No.24342

誤差について
投稿者---miz(2005/11/23 20:20:33)


REEさん、まきじさん

ありがとうございます。誤差について理解できました。


この投稿にコメントする

削除パスワード

No.24347

Re:追記です。
投稿者---かずま(2005/11/23 23:13:42)


> 0.34 OK
> 12.34 NG
> 122.34 OK
> 1222.34 NG
> 12222.34 OK
> ・・・
>
> と整数部が奇数のときだけ起こるようですが、どうしてでしょうか?
0.34 を 2進で表すと
   0.01010111000010100011110101110000101000111101011100001010001111010......
と無限小数になります。

計算機内部の浮動小数点表現では、有限のビット数でしか保持できません。
現在の一般的なものは、53ビットの精度を持つことができます。
したがって、左端の 1 から 54ビット目を四捨五入して 53ビットにしています。

    0.34:              0.010101110000101000111101011100001010001111010111000011
   12.34:           1100.0101011100001010001111010111000010100011110101110
  122.34:        1111010.0101011100001010001111010111000010100011110110
 1222.34:    10011000110.010101110000101000111101011100001010001111
12222.34: 10111110111110.010101110000101000111101011100001010010

0.34 は 54ビット目が 1なので、切り上げになり、ちょっと大きい値になっています。
整数部分があると、そこにビット数を取られ、小数部分のビット数は減ります。
12.34 は 54ビット目が 0 なので、切捨てになり、ちょっと小さい値になっています。
このようなわけで、0.34000... になったり、0.33999... になったりするのです。



この投稿にコメントする

削除パスワード

No.24351

Re:追記です。
投稿者---miz(2005/11/24 16:08:13)


大変ご丁寧な説明ありがとうございます。
今までそこまで深いところまで考えてプログラミングしていなかったので
今回の問題で明確となり、理解できました。

しかし、本題の正しい小数をどう出すか?という問題は解決していませんが・・・。元々内部では2進数で扱われているので不可能と考えたほうが良いのでしょうか・・・。


この投稿にコメントする

削除パスワード

No.24338

Re:作ってみましたが、挙動がおかしいです。
投稿者---まきじ(2005/11/23 19:57:07)


>何か対策方法は無いでしょうか?

文字列として操作したら如何?

#include<stdio.h>

int main(void){

    double b,d = 12.34;
    int a;
    char buf[32];
    
    sprintf(buf,"%f",d);
    sscanf(buf,"%d.%lf",&a,&b);
    
    while(b > 1) b = b / 10.0;
    
    printf("%d \n %f\n",a,b);
    
}



この投稿にコメントする

削除パスワード

No.24344

Re:作ってみましたが、挙動がおかしいです。
投稿者---miz(2005/11/23 20:22:30)


ありがとうございます。
fprintfを使わずにしたいのですが・・・。
もう少し考えてみることにします。


この投稿にコメントする

削除パスワード

No.24346

Re:作ってみましたが、挙動がおかしいです。
投稿者---Craft(2005/11/23 21:33:55)


>文字列として操作したら如何?

雑談ですが、
sprintf()で浮動小数を文字列に変換できることをしらなかったころ、
ecvt(),fcvt()で苦労して文字列化してたことがあったのを思い出しました。


この投稿にコメントする

削除パスワード

No.24350

Re:作ってみましたが、挙動がおかしいです。
投稿者---miz(2005/11/24 15:17:39)


>>何か対策方法は無いでしょうか?
>
>文字列として操作したら如何?

教えてもらったコードについても参考にさせて頂きましたが、
最後の行をprintf("%d \n %.30f\n",a,b);と変更すると
実際は10で割っているため誤差が生じているようです・・・。



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧