Category: 開発

銀行丸めと四捨五入。


というわけで、端数の丸め処理についてです。

端数処理ということで、たぶん思いつくのは、

  • 切り捨て
  • 切り上げ
  • 四捨五入

こんなところではないかと思います。

ここで、テストデータとして

11.4, 11.5, 11.6, 12.4, 12.5, 12.6

という6つのデータを用意します。
それぞれの処理についてですが、通り下記のようになります。

データ切り捨て切り上げ四捨五入
11.4111211
11.5111212
11.6111212
12.4121312
12.5121313
12.6121313

 

C や C# そして Ruby や Java などでは、実数を整数に丸める際、
単純にキャストしますと切り捨てますが、

round 関数で丸める際に、挙動が異なります。

Python:
image

Ruby:
image

C#: (自作のシェル経由でごめんなさい)
image

 

C や Ruby, Java では四捨五入がデフォルトで行われますが、
C# では、銀行丸めがデフォルトで行われます。

正式名称は 「最近接偶数への丸め」と言いますが、
「銀行丸め」のほか、「JIS丸め」「ISO丸め」とも言われます。

[Wikipedia の解説記事]

JIS丸めとは?
http://homepage1.nifty.com/s_miyake/hp/jisround.htm

JIS Z 8401
http://www.jisc.go.jp/app/pager?id=94037

 

上の記事の文章を用いて、簡単に説明すれば、

N桁で丸める場合
第N桁が偶数なら 5以下は切り捨て。それ以外は切り上げ。
第N桁が奇数なら 5未満は切り捨て。それ以外は切り上げ。

 

この挙動について、
11.5 と 12.5 という2つの値を整数値に丸めるという場合で説明しますと、

まず 11.5 の場合。
整数値に丸めるので、整数第1位に丸めることになります。

この場合、整数第1位の値は 1 となり、「奇数」です。
次にこの一つ下の値を参照し、 5 であるため、奇数で5未満でないため切り上げ。

よって、 12 となります。

 

次に 12.5 の場合。

同様に整数第1位の値を見ると 2 となり「偶数」です。
一つ下の値は 5 であるため、偶数で5以下のため切り捨て。

よって、12 となります。

 

ただどうしてこういう丸め方をしているかというと、
主に銀行や統計などにおいて、誤差を小さくするために用いられています。

整数に丸める時の注意 – DiaryException
http://d.hatena.ne.jp/LaclefYoshi/20110430/1304138274

こちらの記事におもしろい実験結果がありますので、参照して頂けたら。

 

上記ブログで用いられている R という言語は、統計に特化した処理系ですので、
やはり誤差を抑えるために、銀行丸めが行われているものと思われます。

 

というわけで、先ほどの結果に、銀行丸めと合計を追加すると以下のようになります。

 

データ切り捨て切り上げ四捨五入銀行丸め
11.411121111
11.511121212
11.611121212
12.412131212
12.512131312
12.612131313

 

というわけで、統計やトレードなどを行う場合はありがたいわけですが、
どうしても四捨五入を行わなければならない場合があります。

その場合は、Math.Round(val) としているところを、

Math.Round(val, MidpointRounding.AwayFromZero);

とすることで解決可能です。

image

 

ではではー!

小学生にも情報教育をば。


どうもみむらです。

いきなり質問ですが、下記の2つの文章の共通点をあげてください。

A.里の秋。

静かな静かな 里の秋
お背戸に木の実の 落ちる夜は
ああ 母さんとただ二人
栗の実 煮てます いろりばた

B.静かな湖畔

静かな湖畔の 森のかげから
もう起きちゃいかがと カッコが鳴く
カッコ カッコ
カッコ カッコ カッコ

 

はい、もうわかりましたよね。

こたえは、誰しもがわかるあれです。

Continue reading »

Console Twitter を公開しました。


image

ておくれてない、まだ、まだだっ!!
ということでみむらです。

先日の OAuth の記事 を書いた後、やっぱりクライアントを作りましょうということで。

ttytter っぽいものを意識しましたが、自分が使いやすいように作ってみました。

 

Microsoft .NET Framework 3.5 がある環境であれば実行可能です。
(Windows 7 では標準搭載)

 

http://mimumimu.net/software/#ConsoleTwitter
上記URL よりダウンロード可能です。

 

ただつぶやくだけではなく、下記のコマンドを使うことで様々な操作も可能です。

/repリプライ一覧を表示
/rep (番号) (ツイート)リプライを送ります。

ex) /rep 01 ておくれてない!
/favお気に入りに登録したツイートを表示します。
/fav (番号)お気に入りに登録します。
/unfav (番号)お気に入りを解除します。
/rt (番号)リツイートします。
/find (テキスト)指定したテキストで Twitter 上のツイートを検索して表示します。

 

コンソールで表示されて、全部がキーで行うということで、
シンプルでかつ、操作も覚えやすいのでは無いでしょうか。

 

ということで、よろしくお願いします-。


追記:ソースコード公開しました。

https://github.com/mimura1133/Console-Twitter

Twitter の OAuth 1.0 認証を自分でコード書いてやってみた。


みむらです。

ひとまず、おべんきょーということで、後からも分かるように、
変数を多く使って文字列出力をふんだんに出しながら。

ソースコードが、海から来た侵略者に侵略されていますが、
そんなもの全く気にしない、むしろ、侵略されていないでゲソ!

—-

参考資料:

* http://oauth.net/core/1.0
* http://hueniverse.com/oauth/guide/authentication/
* https://dev.twitter.com/docs/auth/authorizing-request/

—-

https://gist.github.com/1395485

using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;

/*
 * この辺を参考に:
 * 
 * http://oauth.net/core/1.0
 * http://hueniverse.com/oauth/guide/authentication/
 * https://dev.twitter.com/docs/auth/authorizing-request
 */

namespace Direct_Commit_Twitter
{
    class Program
    {

        static void Main(string[] args)
        {
            //
            // 使うパラメータは次のようなもの。
            //
            // OAuth Consumer Key       : Consumer Key そのまま。
            // OAuth Token              : Access Token そのまま。 (今回はこれも取得。)
            // OAuth Nonce              : ランダム文字列を与える。 (毎回変更する。)
            // OAuth Signature          : OAuth Signature 以外の値で HMAC-SHA1 をとった値。
            // OAuth Signature Method   : Twitter は HMAC-SHA1 指定っぽいので HMAC-SHA1.
            // OAuth Time Stamp         : UNIX 時間 (1970-01-01 UTC からの秒数) を与える。
            //                          : (今回は GetUNIXTime() メソッドで取得します。)
            // OAuth Version            : 今回は 1.0 を使うので、1.0.
            //

            string consumer_key = "oDcUp76alv6VctYvRx2g";
            string consumer_secret = "mg1U9TEFVafIPQm0Y0YuLR8EZatXiDBvPLiiCConzbg";

            string access_token = "";
            string access_secret = "";

            string tweet_text = "ゲソーゲソー";

            /************************ 以下、黙々と処理 ********************/

            string[] verify_token;

            if (access_token == "" || access_secret == "")
            {

                #region 01. Request Token を取得しなイカ?
                {
                    Console.WriteLine("01 - Token を取得しなイカ?");
                    Console.WriteLine("-------------------------------------------------");

                    Random rand = new Random();
                    byte[] nonce_b = new byte[64];

                    rand.NextBytes(nonce_b);

                    string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString();
                    long unixtime = GetUNIXTime();

                    //
                    // OAuth Signature 生成のために、それ以外で仮のリクエスト文字列を作成する。
                    // この際、各パラメータは ABC 順にソートされている必要がある。
                    //
                    string signature_request = "POST&" + UrlEncode("https://api.twitter.com/oauth/request_token");
                    signature_request += "&" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, null, null, null));

                    //
                    // ちゃんとしたリクエスト文字列を作る。
                    //
                    string signature = GetSignature(consumer_secret, null, signature_request);
                    string param = MakeParamString(consumer_key, nonce, signature, unixtime, null, null, null);

                    DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, null, null, null);
                    return;
                    //
                    // 問い合わせ。
                    //
                    Console.WriteLine("* Access : https://api.twitter.com/oauth/request_token?" + param);
                    HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/oauth/request_token?" + param);
                    hwr.Method = "POST";
                    WebResponse ret = hwr.GetResponse();
                    verify_token = new StreamReader(ret.GetResponseStream()).ReadToEnd().Split('&');

                    ret.Close();

                    Console.WriteLine();
                    Console.WriteLine("Response : ");
                    foreach (string s in verify_token)
                        Console.WriteLine("> " + s);
                }
                #endregion

                #region 02. Access Token を取得しなイカ?
                {
                    Console.WriteLine();
                    Console.WriteLine("02 - Access Token を取得しなイカ?");
                    Console.WriteLine("-------------------------------------------------");

                    string request_token = "";
                    string request_secret = "";

                    //
                    // ブラウザ開いて認証。
                    //
                    foreach (string s in verify_token)
                    {
                        int p = s.IndexOf("oauth_token=");
                        if (p != -1)
                        {
                            request_token = s.Substring(p + "oauth_token=".Length);
                            break;
                        }
                    }
                    Console.WriteLine("- OAuth Token : " + request_token);
                    Console.WriteLine("* Browser Open : https://twitter.com/oauth/authorize?oauth_token=" + request_token);
                    Process.Start("https://twitter.com/oauth/authorize?oauth_token=" + request_token);

                    //
                    // PIN を入力させる。
                    //
                    Console.Write("\nINPUT PIN : ");
                    string pin = Console.ReadLine();

                    foreach (string s in verify_token)
                    {
                        int p = s.IndexOf("oauth_token_secret=");
                        if (p != -1)
                        {
                            request_secret = s.Substring(p + "oauth_token_secret=".Length);
                            break;
                        }
                    }


                    //
                    // 以下 Twitter ともくもく通信。
                    //

                    Random rand = new Random();
                    byte[] nonce_b = new byte[64];

                    rand.NextBytes(nonce_b);

                    string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString();
                    long unixtime = GetUNIXTime();

                    //
                    // Signature 生成のための一時的なリクエスト文字列を作成。
                    //
                    string signature_request = "POST&" + UrlEncode("https://api.twitter.com/oauth/access_token");
                    signature_request += "&" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, request_token, pin, null));

                    string signature = GetSignature(consumer_secret, request_secret, signature_request);
                    string param = MakeParamString(consumer_key, nonce, signature, unixtime, request_token, pin, null);

                    DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, request_token, request_secret, pin);

                    //
                    // 問い合わせ。
                    //
                    Console.WriteLine("* Access : https://api.twitter.com/oauth/access_token?" + param);
                    HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/oauth/access_token?" + param);
                    hwr.Method = "POST";
                    hwr.Headers.Add("Authorization", "OAuth");

                    WebResponse ret = hwr.GetResponse();
                    verify_token = new StreamReader(ret.GetResponseStream()).ReadToEnd().Split('&');

                    ret.Close();

                    Console.WriteLine();
                    Console.WriteLine("Response : ");
                    foreach (string s in verify_token)
                    {
                        if (s.IndexOf("oauth_token=") != -1)
                            access_token = s.Substring(s.IndexOf("=") + 1);

                        if (s.IndexOf("oauth_token_secret=") != -1)
                            access_secret = s.Substring(s.IndexOf("=") + 1);

                        Console.WriteLine("> " + s);
                    }
                }
                #endregion

            }

            #region 03. つぶやかなイカ?
            {
                Console.WriteLine();
                Console.WriteLine("03 - つぶやかなイカ?");
                Console.WriteLine("-------------------------------------------------");
                
                Random rand = new Random();
                byte[] nonce_b = new byte[64];

                rand.NextBytes(nonce_b);

                string nonce = Math.Abs(BitConverter.ToInt64(nonce_b, 0)).ToString();
                long unixtime = GetUNIXTime();

                string tweet_data = UrlEncode(tweet_text);

                string signature_request = "POST&" + UrlEncode("https://api.twitter.com/1/statuses/update.xml");
                signature_request += "&include_entities%3Dtrue%26" + UrlEncode(MakeParamString(consumer_key, nonce, null, unixtime, access_token, null, tweet_data));
                string signature = GetSignature(consumer_secret, access_secret, signature_request);

                string header_param = "OAuth oauth_consumer_key=\"" + UrlEncode(consumer_key) + "\",oauth_signature_method=\"HMAC-SHA1\"," +
                                      "oauth_timestamp=\"" + unixtime + "\",oauth_nonce=\"" + UrlEncode(nonce) + "\"," +
                                      "oauth_version=\"1.0\",oauth_token=\"" + UrlEncode(access_token) + "\"," +
                                      "oauth_signature=\"" + UrlEncode(signature) + "\",";

                DebugParamOut(consumer_key, consumer_secret, nonce, signature, unixtime, access_token, access_secret, null);
                Console.WriteLine("* Access : https://api.twitter.com/1/statuses/update.xml");
                Console.WriteLine("* Tweet at : " + tweet_text);

                HttpWebRequest hwr = (HttpWebRequest)HttpWebRequest.Create("https://api.twitter.com/1/statuses/update.xml");
                hwr.Method = "POST";
                hwr.ServicePoint.Expect100Continue = false;
                hwr.Headers.Add(HttpRequestHeader.Authorization, header_param);
                hwr.ContentType = "application/x-www-form-urlencoded";
                var s = new StreamWriter(hwr.GetRequestStream());
                s.Write("status=" + tweet_data + "&include_entities=true");
                s.Close();

                WebResponse ret = hwr.GetResponse();
                Console.WriteLine();
                Console.WriteLine("Response:");
                Console.WriteLine("> "+(new StreamReader(ret.GetResponseStream()).ReadToEnd()));

            }
            #endregion
        }

        // UNIX 時間を返す。
        static long GetUNIXTime()
        {
            return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
        }

        // URLエンコード (どうやらエスケープ文字は大文字にしないといけないらしい。)
        static string UrlEncode(string str)
        {
            string s = HttpUtility.UrlEncode(str);
            return _UrlEncodeUpper(s);
        }

        static string _UrlEncodeUpper(string str)
        {
            int p = str.IndexOf("%");
            if (p != -1)
            {
                str = str.Substring(0, p) + str.Substring(p, 3).ToUpper() + _UrlEncodeUpper(str.Substring(p + 3));
            }
            return str;
        }

        // パラメータ文字列を生成
        static string MakeParamString(string oauth_consumer_key, string oauth_nonce, string oauth_signature, long oauth_timestamp, string oauth_token, string oauth_verifier, string status)
        {
            string param = "oauth_consumer_key=" + oauth_consumer_key + "&oauth_nonce=" + oauth_nonce;

            if (oauth_signature != null)
                param += "&oauth_signature=" + oauth_signature;

            param += "&oauth_signature_method=HMAC-SHA1" + "&oauth_timestamp=" + oauth_timestamp;

            if (oauth_token != null)
                param += "&oauth_token=" + oauth_token;

            if (oauth_verifier != null)
                param += "&oauth_verifier=" + oauth_verifier;
            
            param += "&oauth_version=1.0";

            if (status != null)
                param += "&status=" + status;

            return param;
        }

        // Consumer Secret をKey とした、リクエスト文字列のハッシュを求める。
        static string GetSignature(string consumer_secret, string access_token_secret, string param)
        {
            HMACSHA1 hmacsha1 = new HMACSHA1();
            hmacsha1.Key = Encoding.ASCII.GetBytes(consumer_secret + "&" + access_token_secret);
            byte[] hash = hmacsha1.ComputeHash(Encoding.ASCII.GetBytes(param));
            
            return Convert.ToBase64String(hash);
        }

        // よくやる出力をまとめてみる。
        static void DebugParamOut(string oauth_consumer_key, string oauth_consumer_secret, string oauth_nonce, string oauth_signature, long oauth_timestamp, string oauth_token, string oauth_token_secret, string oauth_verifier)
        {
            Console.WriteLine("- OAuth Consumer Key = " + oauth_consumer_key);
            Console.WriteLine("- OAuth Consumer Secret = " + oauth_consumer_secret);
            Console.WriteLine("- OAuth Nonce = " + oauth_nonce);
            if (oauth_signature != null)
                Console.WriteLine("- OAuth Signature = " + oauth_signature);
            Console.WriteLine("- OAuth Time Stamp = " + oauth_timestamp);
            if (oauth_token != null)
                Console.WriteLine("- OAuth Access Token = " + oauth_token);
            if (oauth_token_secret != null)
                Console.WriteLine("- OAuth Access Token Secret = " + oauth_token_secret);
            if (oauth_verifier != null)
                Console.WriteLine("- OAuth Verifier = " + oauth_verifier);
        }
    }
}

 

とりあえず、記事自体がむちゃくちゃ長くなるので、
解説云々は次の記事に。

Twitterizer で UserStream を取得する。


みむらです。結構簡単だったのでぺけぺけ。

 


1.Visual Studio を立ち上げてプロジェクトを作る。

 

image

image

でけた。

 


2.Package Manager を起動して、 Twitterizer を入れる。

 

使い方および起動方法は以前書いた記事を : NuGet で簡単にパッケージを導入する

image

image

だん。

 


3.Twitter にアプリケーションを登録する。

 

https://dev.twitter.com/apps へアクセス。

image

画面の右上にある 「Create a new application」 をクリック。

 

image

こういう画面が出てきます。

 

ここでは、次の項目を入力します (なお、各項目は日本語でも問題ありません。):

項目名

説明

Nameアプリケーションの名前を入力します。
10文字です。
やぎ、そしてやぎさん、ゆうびんさん。
Descriptionどういうアプリケーションかという説明文を入力します。
10文字~200文字です。
めーと鳴いて、朝と夜を知らせるが、たまに昼間も鳴いてTL を荒らす。
WebSiteウェブサイトのアドレスを入力します。http://mimumimu.net/
Yes, I agree上に表示されている、Developer Rules Of The Road に納得できるのであればチェックをします。 
CAPTCHA下に表示される2つの文字列を入力します。 

 

image

 

適当に入力したら、一番下の 「 Create your Twitter application 」 をクリックします。

image

こんな感じで、アプリケーションが登録されます。

 

この際、

image

ページの下の方の OAuth settings に表示されている、
Consumer keyConsumer secret をメモしておいてください。

(なお、このアプリケーションは記事投稿前に削除しているので、Key と Secret は無効です。

 


4.コードを書く。

 

Visual Studio に戻ってコードを書きます。

image

 

適当に書いてみたのが下記のコード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Twitterizer;
using Twitterizer.Streaming;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //
            // 先ほどメモした ConsumerKey と ConsumerSecret をここに入力。
            //
            string consumerKey = "GfX2lsqHQAyObh1vPaTUuQ";
            string consumerSecret = "ffLnE720PHwBHeZShGSEw6qTj5UQD1KgMoAqT9IhvuQ";

            //
            // アクセストークンを取得するために、ブラウザを立ち上げて認証ページを表示させる。
            //
            OAuthTokenResponse req = 
                    OAuthUtility.GetRequestToken(consumerKey, consumerSecret,"oob");
            Process.Start(OAuthUtility.BuildAuthorizationUri(req.Token).ToString());

            //
            // キーを入力させる。
            //
            Console.Write("YOUR KEY : ");
            string pin = Console.ReadLine();

            //
            // 認証情報を OAuthTokens に格納する。
            //
            OAuthTokenResponse actToken =
                    OAuthUtility.GetAccessToken(consumerKey, consumerSecret, req.Token, pin);
            OAuthTokens token = new OAuthTokens
            {
                ConsumerKey = consumerKey,
                ConsumerSecret = consumerSecret,
                AccessToken = actToken.Token,
                AccessTokenSecret = actToken.TokenSecret
            };

            //
            // 第1引数に認証情報、
            // 第2引数にクライアント名
            // 第3引数に取得に関する条件等を指定(今回は null)
            //
            var Stream = new TwitterStream(token, "侵略でゲソ", null);

            Stream.StartUserStream(null, null,
                    (x) => { Console.WriteLine("ID : " + x.User.Name + " - " + x.Text); },
                    null, null, null, null, null);

            while (true) { }
        }
    }
}

 

ちょっと一言:

この際、プログラムが動作しないようであれば、
大抵が .NET Framework 4.0 Client Profile を利用していることが原因なので、変えておきます。

 

1.プロジェクトファイルを右クリックして、プロパティを選ぶ。

 

image

 

2.「対象のフレームワーク」を 「.NET Framework 4」に変える。

 

image

読み込み直すかどうかのダイアログが出るので、「はい」をクリックします。

 


5.実行する。

 

image

 

「連携アプリを認証」をクリック。

image

 

見づらいですが、表示された番号と同じ物をアプリケーションに入力します。

image

うまくいくとこのように、ツイートがたらたら流れてきます。