20190704のC#に関する記事は5件です。

C# double型 について

はじめに

  • 筆者が疑問に思って検証した結果を書いたもので、double型のすべてを記したものではない
  • この記事内の「出力」というのは、Console.WriteLineの表示結果のこと
  • 「16進数出力」は、BitConverter.DoubleToInt64Bits()を使用して、doubleのビットの状態を表示したもの

各種定数のビット

定数 16進数出力
0 0x0000000000000000
1 0x3FF0000000000000
MinValue 0xFFEFFFFFFFFFFFFF
MaxValue 0x7FEFFFFFFFFFFFFF
Epsilon 0x0000000000000001
NaN 0xFFF8000000000000

0.99… どのくらいまでなら正確に保持できるか

結論

  • コード上で表記:0.9999999999999999
  • 16進数の場合:0x3FEFFFFFFFFFFFFF

検証:コード上で直接入力して出力した結果

  • 9の数が17以上になると、1.0となってしまう。
  • 0x3FEFFFFFFFFFFFFFは、1.0 未満だが、出力すると 1.0 となる。
9の数 コード上の表記 10進数出力 16進数出力
1 0.9 0.9 0x3FECCCCCCCCCCCCD
2 0.99 0.99 0x3FEFAE147AE147AE
15 0.999999999999999 0.999999999999999 0x3FEFFFFFFFFFFFF7
16 0.9999999999999999 1.0 0x3FEFFFFFFFFFFFFF
17 0.99999999999999999 1.0 0x3FF0000000000000
18 0.999999999999999999 1.0 0x3FF0000000000000

検証:1.0から徐々に小さくしていった場合

  • BitConverter.Int64BitsToDouble()を使用して、整数から実数に変換し出力
  • 0x3FEFFFFFFFFFFFFFは、1.0 未満だが、出力すると 1.0 となる。
元の整数 実数出力
0x3FF0000000000000 1.0
0x3FEFFFFFFFFFFFFF 1.0
0x3FEFFFFFFFFFFFFE 1.0
0x3FEFFFFFFFFFFFFD 1.0
0x3FEFFFFFFFFFFFFC 1.0
0x3FEFFFFFFFFFFFFB 0.999999999999999
0x3FEFFFFFFFFFFFFA 0.999999999999999

doubleで正確に保持可能な整数の最大値

結論

  • 9007199254740992
  • 16進数:0x20000000000000

検証:long→double→longの順番でキャスト

  • 0x20000000000001 は、longに戻した後 0x20000000000000 になってしまう。

各出力結果

元のlong値 代入後のdouble値(16進数出力) キャスト後のlong値
0x1FFFFFFFFFFFFF 0x433FFFFFFFFFFFFF 0x1FFFFFFFFFFFFF
0x20000000000000 0x4340000000000000 0x20000000000000
0x20000000000001 0x4340000000000000 0x20000000000000

ToStringのフォーマット

double.Epsilon を小数表記で出力する方法

結論:桁プレースホルダーを使用する

"0.####・・・"の、"#"が338個並んだフォーマットを使用する。

検証:書式指定子を使用した場合

  • 小数表記で表示されず、指数表記になる。
  • 精度指定子では99桁が限界、100桁以上は"F100"のように出力されてしまう。
  • 補足:C,E,Pは、そもそも目的が違うので、ここには載せていません。
書式指定子 出力結果
F99 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
G99 4.9406564584124654E-324
N99 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
R99 4.94065645841247E-324

検証:桁プレースホルダーを使用した場合

  • 桁プレースホルダーとは、"0.####"のように書いたフォーマットのこと
#の数 出力結果
337 0.000(略)00049406564584125
338 0.000(略)000494065645841247
339 0.000(略)000494065645841247
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

複数の yield returnで失敗

今や滅多に使わないyield return ですが、
yield returnの方が可読性良いな、と思った個所があったので久々に書いたらしくじりました。
ダサい失敗で恥ずかしいですが、2回もやったので備忘録。

概要

yield return で返り値を複数パターンの条件で分けたかった。

失敗したコード

foreach (var data in datalist)
{
    var data2 = hoge(data);

    if (data2 == null)
    {
        yield return null;
    }
    yield return hogehoge(data2);
}

ifの中のyield return ではそのループ処理は止まりません。
よってifの後のyield return も評価されます。
この時一回のループで2要素が返されてしまいます。
今回はhogehoge(null)で例外が出たので気づけましたが、
例外出ないと結構厄介なバグになるかもしれませんね。

どうもreturn 句でそこで処理が止まるイメージがある様です。
でもそしたらループ毎止まるので、その点でも間違ってますね。

上手く行くコード

foreach (var data in datalist)
{
    var data2 = hoge(data);

    if (data2 == null)
    {
        yield return null;
    }
    else
    {
        //ifでどちらかのyield 
        yield return hogehoge(data2);
    }
}
foreach (var data in datalist)
{
    var data2 = hoge(data);

    if (data2 == null)
    {
        yield return null;
        //ちゃんと帰りましょう
        continue;
    }
    yield return hogehoge(data2);

}
foreach (var data in datalist)
{
    var data2 = hoge(data);

    if (data2 == null)
    {
        //null不要ならそのままcontinue;
        continue;
    }
    yield return hogehoge(data2);

}
foreach (var data in datalist)
{
    var data2 = hoge(data);
    //1行で表現したり
    yield return data2 == null ? null : hogehoge(data2);

}

yield returnを複数書かなければならないと思ってしまう設計自体が悪そうなんで、
もっと構造自体を変えられないか検討した方が良いかも知れませんね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LiBOVRを.libから.dllに変換する

概要

Oculus riftのtouch controllerを用いたアプリケーションをC#で書く必要があり、libをdllに変換しました。libをdllに変換する基本的な方法は、visual studioのプロジェクトでdll生成用のものがあるので、それを使う場合が多いです。しかし今回はlibのプロジェクトもしくはソリューションを用いてdllに変換します。ただし、以下の方法はOculus SDKのLiBOVRのみに適用できる方法かもしれないので、参考にする方は注意して頂けると幸いです!

実行環境

次に実行環境を示します。

Soft and Hard バージョン
Windows 10 pro 16.04
Oculus SDK 1.37.0
Visual studio 2015 Community Update 3

変換手順

今回の手順では、Oculus SDKのLiBOVRのディレクトリ内にあるVisual studio 2015用のプロジェクトを用いてdllを出力します。まずは、そのプロジェクトを開きます。該当のプロジェクトは、Oculusの公式ページからダウンロードできるOculus SDKの中にあるので、Oculus SDKをダウンロードします。

Oculus SDKをダウンロード

ダウンロード後、zipを解凍し、以下のディレクトリにある、プロジェクトを開きます。

\ovr_sdk_win_1.37.0\LibOVR\Projects\Windows\VS2015

以上が前準備となります。次に、dll用のVisual Studio 2015のプロジェクトの設定手順について述べます。

1. プロジェクト名を選択した状態で、右クリックし、プロパティを開きます。

5.png

2. 構成プロパティ -> プロジェクトの規定値 -> 構成の種類をダイナミックライブラリ(.dll)に変更します。

1.png

ここで、dllが生成されるディレクトリを変更する場合には、全般->出力ディレクトリの指定ディレクトリを変更します。

3. リンカー -> 入力 -> 追加の依存ファイルに、msvcrt.lib,winmm.lib,setupapi.libを追加します。

3.PNG

4. プロパティページの右下のOKを選択し、プロパティページを閉じます。

5. プロジェクトをリビルドし、dllを生成します。

4.PNG

生成されたdllは、全般->出力ディレクトリで指定しているディレクトリに出力されています。

まとめ

今回は、C#でアプリケーションを作るために、dllをlibから生成しました。次は、C#を用いたアプリケーションを作りたいと思います。また、上記の内容で間違っている箇所や、改善したほうが良い点等ありましたら教えていただけると嬉しいです!

参考にしたもの

https://forums.oculusvr.com/developer/discussion/7979/sdk-0-3-1-and-compiling-libovr-to-dll
https://stackoverflow.com/questions/40780047/build-lib-as-dll-instead

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

デザインパターン学習_メモ_Iteratorパターン

Javaで学ぶデザインパターン入門

結城浩「Javaで学ぶデザインパターン入門」を手元に環境があったC#で勉強

Iterator パターン

今回はIteratorパターン
とりあえず、参考書に乗ってあるサンプルコードは見ずに、
クラス図を見て実装した。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternLearn.IteratorLearn
{
    /// <summary>
    /// Mainはテキスト通り
    /// </summary>
    class Test
    {
        public static void Main(string[] args)
        {
            BookShelf bookShelf = new BookShelf(4);
            bookShelf.AppendBook(new Book("Javaで学ぶデザインパターン入門1"));
            bookShelf.AppendBook(new Book("Javaで学ぶデザインパターン入門2"));
            bookShelf.AppendBook(new Book("Javaで学ぶデザインパターン入門3"));
            bookShelf.AppendBook(new Book("Javaで学ぶデザインパターン入門4"));
            ITerator it = bookShelf.iTerator();
            while (it.HasNext())
            {
                Book book = (Book)it.Next();
                Console.WriteLine(book.Name);
            }
            Console.Read();
        }
    }

    public interface Aggrregate
    {
        ITerator iTerator();
    }

    /// <summary>
    /// 要素の数え上げ、ループ変数のような役割
    /// </summary>
    public interface ITerator
    {
        bool HasNext();
        object Next();
    }

    public class BookShelfIterator : ITerator
    {
        private BookShelf bookShelf;
        private int index;

        public BookShelfIterator(BookShelf bookShelf)
        {
            this.bookShelf = bookShelf;
        }

        public bool HasNext()
        {
            return bookShelf.GetLength() >= (index + 1) ? true : false;  
        }

        public object Next()
        {
            if (HasNext())
            {
                this.index = index + 1;
                return bookShelf.GetBookAt(index);
            } else
            {
                return null;
            }
        }
    }

    /// <summary>
    /// Aggregateを実装すること
    /// → 内部でIteratorメソッドを実装する必要がある。
    /// </summary>
    public class BookShelf : Aggrregate
    {
        private Book[] books;
        private int last;

        public BookShelf()
        {
            this.books = new Book[] { };
            this.last = 0;
        }

        /// <summary>
        /// Mainを見た後に追加した
        /// </summary>
        /// <param name="last"></param>
        public BookShelf(int itemNum)
        {
            this.books = new Book[itemNum];
            this.last = 0;
        }

        public Book GetBookAt(int index)
        {
            return books[index];
        }

        public void AppendBook(Book book)
        {
            books[last] = book;
            last = last + 1;
        }

        public int GetLength()
        {
            return last;
        }

        /// <summary>
        /// ここが重要
        /// Iteratorメソッドを実装する際に、
        /// Iteratorインターフェイスを実装しているクラスのコンストラクタを
        /// 呼び出してる
        /// → Iteratorの対象を切り替えるのが簡単
        /// </summary>
        /// <returns></returns>
        public ITerator iTerator()
        {
            return new BookShelfIterator(this);
        }
    }

    public class Book
    {
        public string Name { get; set; }

        public Book(string name)
        {
            this.Name = name;
        }
    }
}



エラーだった。
BookShelfクラスNextメソッドでインデックスの操作を間違っていた。
以下で正しく動く(あまりきれいなやり方ではないけど)

public object Next()
{
    if (HasNext())
    {
        this.index = index + 1;
        return bookShelf.GetBookAt(index - 1);
    } else
    {
        return null;
    }
}

重要な考え方

Iteratorを使うことで、実装とは切り離して、数え上げを行うことができる。
→ BookShelfをそのまま用いず、BookShelf中のIterator(BookSshelfIterator)を使用
  BookShelfの中身は、Iteratorが知っていればよい。
そのため、BookShelfの実装を変更しても、Main関数などそれを呼び出す側の実装を変更せずにすむ。

練習問題1-1

上記のBookShelfクラスでは上限を超えて本を収納することができない。
上限を超えても本を格納できるように変更せよ。

    public class BookShelf : Aggrregate
    {
        private List<Book> books; // 変更箇所
        private int last;

        public BookShelf()
        {
            this.books = new List<Book>(); //変更箇所
            this.last = 0;
        }

        /// <summary>
        /// Mainを見た後に追加した
        /// </summary>
        /// <param name="last"></param>
        public BookShelf(int itemNum)
        {
            this.books = new List<Book>(itemNum); //変更箇所
            this.last = 0;
        }

        public Book GetBookAt(int index)
        {
            return books[index];
        }

        public void AppendBook(Book book)
        {
            books.Add(book); //変更箇所
            last = last + 1;
        }

        public int GetLength()
        {
            return last;
        }

        /// <summary>
        /// ここが重要
        /// Iteratorメソッドを実装する際に、
        /// Iteratorインターフェイスを実装しているクラスのコンストラクタを
        /// 呼び出してる
        /// → Iteratorの対象を切り替えるのが簡単
        /// </summary>
        /// <returns></returns>
        public ITerator iTerator()
        {
            return new BookShelfIterator(this);
        }
    }

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

イラストレーターがプログラミングを勉強しようとした話。【1話】

はじめに

この記事は前回の
ノンプログラマーがプログラミングを勉強しようとした話。【前節】
続きです。

タイトル変更しました

ノンプログラマーからイラストレーターが~にタイトルを変更しました。
理由としては、Qitaでノンプログラマーと検索すると。

  • コードは書かないけれど上流で設計やっています
  • 趣味でプログラムしています
  • 基本的にエンジニアとやり取りするポジション(webアプリのディレクションとか)

と、結構知識がある前提で書かれている記事が多くて、僕としてはやっぱり調べ始めた時に引っかかった部分が払拭できないな~という理由。
あとはやはり、需要としては狭くなりますが、デザイナーとかイラストレーターが興味はあるけど取っ掛かりがない状態からの足がかりになればなと。

最終的にこの記事を通して読んでもバリバリコードを書けるようにはならない。

これは 前回の記事で書いておけばよかったんですが、そもそも僕自身が、今バリバリコード書いて実装してますとかじゃないので、1週間でプログラマーになれるとかそういうハックではないです。
あと、セクションによってはデザイナーもシェーダー書いたりpythonでツールゴリゴリ作る人もいるのでそういう人向けではないです。
あくまでも、興味はあるけど取っ掛かりがない。とかプラグラムと聞くとパソコン壊しそうとかそういう人向けになってます。
あとは、エンジニアさんがデザイナーの思考というか、どこから説明すればいいかのヒントとか共通言語化ができればなと。

ではやっと次から本題に入って行きたいとと思います。また内容薄めになってらごめんなさい、多分今回はUnityとC#少し……

わからないことがわからない!

正直最初は本当にこれですね、わからないことがわからない。
まぁそもそも、目に見える物を直感的に作ってる人が多いので、やっぱり数字や英単語が書いてあるだけの画面に向かって唸ってるエンジニアさんは怖いし、黒魔術でも使ってんじゃないかとおもうんですよ。
じゃぁ具体的に何わからないの?って話なんですが。

横文字多すぎ

横文字おおいですよね。

  • オブジェクト
  • パラダイム
  • パース
  • メソッド

やっていけば、まぁそのままの意味なんですけど。
パースとか透視図法の事かと思っちゃいますね。
プログラムというかUnityとかでも、初心者向けと書いてあったり入門と書いてあっても、結構無慈悲に

オブジェクトをインスタンスします

とか書かれているわけですね。
オブジェクト????
インスタンス???
で、更にオブジェクトで調べに行くと概念設計とかの話がバンバン出てくるわけです。

例えば、絵の描き方教えてって言われた時に。

回り込みと立体感を意識して、線を引くといいですね。色は環境光と色の恒常性を意識するといいです。

っていわれてもなぁってなります。
俺は斜め45度の女の子が描きたいんだ。
まぁこんな回答は稀で、だいたい、いい感じに描くとかの返答が帰ってくるかと思います。

ただお互い説明しろと言われても、そういうもんだしなーとしか言えませんしね。

じゃぁどう説明するか。

具体的な事象で説明する

オブジェクト指向プログラミングとはというと、コードを再利用するためにクラスという部品に分ける。
だいたいこんな感じの説明が出てきます。
いやほんと、そのとおりなんですが。
プログラムが部品?どういうことってなります。
イラストって基本フルスクラッチなので、再利用って概念があんまりないです。
漫画だとコマの使い回しとか、よく使う構図とか概念的には有る気がしますが。

イラストで例えると。

イラストレータというこれをクラスとします、絵柄はイラストレーターが具体的に出力する関数とします。
関数の説明が抜けてましたが、関数はプログラムの具体的な部分です a + b = c なんですが、よくわからないとおもいますので、イラストレーターが絵を書く工程が書かれていると思っていただければOKです。

  • NUKO-D(クラス)

    • NUKO-D描く女の子関数
  • 〇〇イラストレーター(クラス)

    • 〇〇イラストレーターが描く可愛い服関数
  • △△イラストレーター(クラス)

    • △△イラストレーターが描くいい感じの背景関数

この3つのクラスとそれぞれに入っている関数を使うことで、処理、ここでいうと一枚のイラストが作れるという感じです。
プログラムのソースコードをのぞくと、英語が+とか=で結ばれていて一見よくわかりませんが。工程や計算などが単語として定義されて、それを組み合わせて有るのでそう見える感じです。
インターネットにこういう便利な関数がまとめられた物がフリー素材や有償素材としておいてあって、用途に合わせて組み合わせて行きます。
webデザインなんかではよくあると思いますが、イラストは基本書き起こすので具体性はないですが、アウトプットする時に脳内で行っている作業に近いとは思います。
もちろん、そのイラストに会わなければ、新たにクラスや処理を作ってあわせて行きます。

今回はここまで

今回はここまでにしようかなと思います。次回は実際どういう環境で具体的に勉強していくかというところ。
Unityに触れていければと思います。
なにか間違いとかあればご指摘お願いします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む